X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;f=m4%2Fc-stack.m4;h=0963cc580eed75982577483ef74aab69489b426d;hb=0a3f7af426469ab51370585e1a3afba66ff24b57;hp=1db2a5065d22a63d12b2b09d6630c39900dbe7a1;hpb=a3f953e86848ed858ed655bba12a7fbbab57f1c5;p=gnulib.git diff --git a/m4/c-stack.m4 b/m4/c-stack.m4 index 1db2a5065..0963cc580 100644 --- a/m4/c-stack.m4 +++ b/m4/c-stack.m4 @@ -1,21 +1,194 @@ # Check prerequisites for compiling lib/c-stack.c. -# Copyright (C) 2002, 2003, 2004, 2008 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Written by Paul Eggert. -# serial 4 +# serial 9 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], [# for STACK_DIRECTION AC_REQUIRE([AC_FUNC_ALLOCA]) + AC_REQUIRE([AC_CANONICAL_HOST]) AC_CHECK_FUNCS_ONCE([setrlimit]) AC_CHECK_HEADERS_ONCE([ucontext.h]) + dnl List of signals that are sent when an invalid virtual memory address + dnl is accessed, or when the stack overflows. + dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }. + case "$host_os" in + sunos4* | freebsd* | dragonfly* | openbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems + FAULT_YIELDS_SIGBUS=1 ;; + hpux*) # HP-UX + FAULT_YIELDS_SIGBUS=1 ;; + macos* | darwin*) # MacOS X + FAULT_YIELDS_SIGBUS=1 ;; + gnu*) # Hurd + FAULT_YIELDS_SIGBUS=1 ;; + *) + FAULT_YIELDS_SIGBUS=0 ;; + esac + AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS], + [Define to 1 if an invalid memory address access may yield a SIGBUS.]) + AC_CACHE_CHECK([for working C stack overflow detection], + [ac_cv_sys_stack_overflow_works], + [AC_TRY_RUN( + [ + #include + #include + #if HAVE_SETRLIMIT + # include + # include + # include + #endif + #ifndef SIGSTKSZ + # define SIGSTKSZ 16384 + #endif + + static union + { + char buffer[2 * SIGSTKSZ]; + long double ld; + long u; + void *p; + } alternate_signal_stack; + + static void + segv_handler (int signo) + { + _exit (0); + } + + static int + c_stack_action () + { + stack_t st; + struct sigaction act; + int r; + + st.ss_flags = 0; + /* Use the midpoint to avoid Irix sigaltstack bug. */ + st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ; + st.ss_size = SIGSTKSZ; + r = sigaltstack (&st, 0); + if (r != 0) + return r; + + sigemptyset (&act.sa_mask); + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; + act.sa_handler = segv_handler; + #if FAULT_YIELDS_SIGBUS + if (sigaction (SIGBUS, &act, 0) < 0) + return -1; + #endif + return sigaction (SIGSEGV, &act, 0); + } + static volatile int * + recurse_1 (volatile int n, volatile int *p) + { + if (n >= 0) + *recurse_1 (n + 1, p) += n; + return p; + } + static int + recurse (volatile int n) + { + int sum = 0; + return *recurse_1 (n, &sum); + } + int + main () + { + #if HAVE_SETRLIMIT && defined RLIMIT_STACK + /* Before starting the endless recursion, try to be friendly + to the user's machine. On some Linux 2.2.x systems, there + is no stack limit for user processes at all. We don't want + to kill such systems. */ + struct rlimit rl; + rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */ + setrlimit (RLIMIT_STACK, &rl); + #endif + + return c_stack_action () || recurse (0); + } + ], + [ac_cv_sys_stack_overflow_works=yes], + [ac_cv_sys_stack_overflow_works=no], + [ac_cv_sys_stack_overflow_works=cross-compiling])]) + + if test $ac_cv_sys_stack_overflow_works = yes; then + AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1], + [Define to 1 if extending the stack slightly past the limit causes + a SIGSEGV which can be handled on an alternate stack established + with sigaltstack.]) + + dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address + dnl of the memory block designated as an alternate stack. But IRIX 5.3 + dnl interprets it as the highest address! + AC_CACHE_CHECK([for correct stack_t interpretation], + [gl_cv_sigaltstack_low_base], [ + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ +#include +#include +#if HAVE_SYS_SIGNAL_H +# include +#endif +#ifndef SIGSTKSZ +# define SIGSTKSZ 16384 +#endif +volatile char *stack_lower_bound; +volatile char *stack_upper_bound; +static void check_stack_location (volatile char *addr) +{ + if (addr >= stack_lower_bound && addr <= stack_upper_bound) + exit (0); + else + exit (1); +} +static void stackoverflow_handler (int sig) +{ + char dummy; + check_stack_location (&dummy); +} +int main () +{ + char mystack[2 * SIGSTKSZ]; + stack_t altstack; + struct sigaction action; + /* Install the alternate stack. */ + altstack.ss_sp = mystack + SIGSTKSZ; + altstack.ss_size = SIGSTKSZ; + stack_lower_bound = (char *) altstack.ss_sp; + stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1; + altstack.ss_flags = 0; /* no SS_DISABLE */ + if (sigaltstack (&altstack, NULL) < 0) + exit (2); + /* Install the SIGSEGV handler. */ + sigemptyset (&action.sa_mask); + action.sa_handler = &stackoverflow_handler; + action.sa_flags = SA_ONSTACK; + if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0) + exit(3); + /* Provoke a SIGSEGV. */ + raise (SIGSEGV); + exit (3); +}]])], + [gl_cv_sigaltstack_low_base=yes], + [gl_cv_sigaltstack_low_base=no], + [gl_cv_sigaltstack_low_base=cross-compiling])]) + if test "$gl_cv_sigaltstack_low_base" = no; then + AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1], + [Define if sigaltstack() interprets the stack_t.ss_sp field + incorrectly, as the highest address of the alternate stack range + rather than as the lowest address.]) + fi + + AC_CACHE_CHECK([for precise C stack overflow detection], ac_cv_sys_xsi_stack_overflow_heuristic, [AC_TRY_RUN( [ @@ -29,10 +202,13 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], # include # include #endif + #ifndef SIGSTKSZ + # define SIGSTKSZ 16384 + #endif static union { - char buffer[SIGSTKSZ]; + char buffer[2 * SIGSTKSZ]; long double ld; long u; void *p; @@ -55,8 +231,8 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], { if (0 < info->si_code) { - /* For XSI heuristics to work, we need uc_stack to describe - the interrupted stack (as on Solaris), and not the + /* For XSI heuristics to work, we need uc_stack to describe + the interrupted stack (as on Solaris), and not the currently executing stack (as on Linux). */ ucontext_t const *user_context = context; char const *stack_min = user_context->uc_stack.ss_sp; @@ -81,8 +257,9 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], int r; st.ss_flags = 0; - st.ss_sp = alternate_signal_stack.buffer; - st.ss_size = sizeof alternate_signal_stack.buffer; + /* Use the midpoint to avoid Irix sigaltstack bug. */ + st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ; + st.ss_size = SIGSTKSZ; r = sigaltstack (&st, 0); if (r != 0) return r; @@ -90,17 +267,25 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], sigemptyset (&act.sa_mask); act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; act.sa_sigaction = segv_handler; + #if FAULT_YIELDS_SIGBUS + if (sigaction (SIGBUS, &act, 0) < 0) + return -1; + #endif return sigaction (SIGSEGV, &act, 0); } - + static volatile int * + recurse_1 (volatile int n, volatile int *p) + { + if (n >= 0) + *recurse_1 (n + 1, p) += n; + return p; + } static int - recurse (char *p) + recurse (volatile int n) { - char array[500]; - array[0] = 1; - return *p + recurse (array); + int sum = 0; + return *recurse_1 (n, &sum); } - int main () { @@ -114,8 +299,7 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], setrlimit (RLIMIT_STACK, &rl); #endif - c_stack_action (); - return recurse ("\1"); + return c_stack_action () || recurse (0); } ], [ac_cv_sys_xsi_stack_overflow_heuristic=yes], @@ -123,7 +307,7 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])]) if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then - AC_DEFINE(HAVE_XSI_STACK_OVERFLOW_HEURISTIC, 1, + AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1], [Define to 1 if extending the stack slightly past the limit causes a SIGSEGV, and an alternate stack can be established with sigaltstack, and the signal handler is passed a context that specifies the @@ -131,7 +315,8 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], with the X/Open System Interface (XSI) option and is a standardized way to implement a SEGV-based stack overflow detection heuristic.]) - fi]) + fi + fi]) AC_DEFUN([gl_PREREQ_C_STACK],