X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fc-stack.c;h=03db242f754aa0c43d6271342abb9ae3bc22c1e4;hb=fdd1b511c5c12912aae79b58e0c5f6ffa0492d6e;hp=044272cc3e105ef592b4f9e1487c3def5b3323cd;hpb=df57f4270959d6679422896ca6f579d048777d81;p=gnulib.git diff --git a/lib/c-stack.c b/lib/c-stack.c index 044272cc3..03db242f7 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -1,7 +1,6 @@ /* Stack overflow handling. - Copyright (C) 2002, 2004, 2006, 2008, 2009 Free Software - Foundation, Inc. + Copyright (C) 2002, 2004, 2006, 2008-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,6 +52,12 @@ typedef struct sigaltstack stack_t; #endif #ifndef SIGSTKSZ # define SIGSTKSZ 16384 +#elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384 +/* libsigsegv 2.6 through 2.8 have a bug where some architectures use + more than the Linux default of an 8k alternate stack when deciding + if a fault was caused by stack overflow. */ +# undef SIGSTKSZ +# define SIGSTKSZ 16384 #endif #include @@ -75,9 +80,9 @@ typedef struct sigaltstack stack_t; #include "ignore-value.h" #if defined SA_ONSTACK && defined SA_SIGINFO -# define SIGACTION_WORKS 1 +# define SIGINFO_WORKS 1 #else -# define SIGACTION_WORKS 0 +# define SIGINFO_WORKS 0 # ifndef SA_ONSTACK # define SA_ONSTACK 0 # endif @@ -99,11 +104,16 @@ static char const * volatile stack_overflow_message; appears to have been a stack overflow, or with a core dump otherwise. This function is async-signal-safe. */ -static void die (int) __attribute__ ((noreturn)); -static void +static _Noreturn void die (int signo) { char const *message; +#if !SIGINFO_WORKS && !HAVE_LIBSIGSEGV + /* We can't easily determine whether it is a stack overflow; so + assume that the rest of our program is perfect (!) and that + this segmentation violation is a stack overflow. */ + signo = 0; +#endif /* !SIGINFO_WORKS && !HAVE_LIBSIGSEGV */ segv_action (signo); message = signo ? program_error_message : stack_overflow_message; ignore_value (write (STDERR_FILENO, program_name, strlen (program_name))); @@ -151,7 +161,7 @@ static volatile int segv_handler_missing; overflow. This function is async-signal-safe. */ static int segv_handler (void *address __attribute__ ((unused)), - int serious) + int serious) { # if DEBUG { @@ -171,17 +181,15 @@ static int segv_handler (void *address __attribute__ ((unused)), /* Handle a segmentation violation that is likely to be a stack overflow and exit. This function is async-signal-safe. */ -static void overflow_handler (int, stackoverflow_context_t) - __attribute__ ((noreturn)); -static void +static _Noreturn void overflow_handler (int emergency, - stackoverflow_context_t context __attribute__ ((unused))) + stackoverflow_context_t context __attribute__ ((unused))) { # if DEBUG { char buf[1024]; sprintf (buf, "overflow_handler emergency=%d segv_handler_missing=%d\n", - emergency, segv_handler_missing); + emergency, segv_handler_missing); write (STDERR_FILENO, buf, strlen (buf)); } # endif @@ -212,29 +220,14 @@ c_stack_action (void (*action) (int)) #elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING -/* Direction of the C runtime stack. This function is - async-signal-safe. */ - -# if STACK_DIRECTION -# define find_stack_direction(ptr) STACK_DIRECTION -# else -static int -find_stack_direction (char const *addr) -{ - char dummy; - return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1; -} -# endif - -# if SIGACTION_WORKS +# if SIGINFO_WORKS /* Handle a segmentation violation and exit. This function is async-signal-safe. */ -static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn)); -static void +static _Noreturn void segv_handler (int signo, siginfo_t *info, - void *context __attribute__ ((unused))) + void *context __attribute__ ((unused))) { /* Clear SIGNO if it seems to have been a stack overflow. */ # if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC @@ -244,7 +237,7 @@ segv_handler (int signo, siginfo_t *info, Note that although both Linux and Solaris provide sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only - Solaris satisfies the XSI heueristic. This is because + Solaris satisfies the XSI heuristic. This is because Solaris populates uc_stack with the details of the interrupted stack, while Linux populates it with the details of the current stack. */ @@ -253,27 +246,24 @@ segv_handler (int signo, siginfo_t *info, if (0 < info->si_code) { /* If the faulting address is within the stack, or within one - page of the stack end, assume that it is a stack - overflow. */ + page of the stack, assume that it is a stack overflow. */ ucontext_t const *user_context = context; char const *stack_base = user_context->uc_stack.ss_sp; size_t stack_size = user_context->uc_stack.ss_size; char const *faulting_address = info->si_addr; - size_t s = faulting_address - stack_base; size_t page_size = sysconf (_SC_PAGESIZE); - if (find_stack_direction (NULL) < 0) - s += page_size; - if (s < stack_size + page_size) - signo = 0; + size_t s = faulting_address - stack_base + page_size; + if (s < stack_size + 2 * page_size) + signo = 0; # if DEBUG { - char buf[1024]; - sprintf (buf, - "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n", - faulting_address, stack_base, (unsigned long) stack_size, - (unsigned long) page_size, signo); - write (STDERR_FILENO, buf, strlen (buf)); + char buf[1024]; + sprintf (buf, + "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n", + faulting_address, stack_base, (unsigned long) stack_size, + (unsigned long) page_size, signo); + write (STDERR_FILENO, buf, strlen (buf)); } # endif } @@ -309,7 +299,7 @@ c_stack_action (void (*action) (int)) sigemptyset (&act.sa_mask); -# if SIGACTION_WORKS +# if SIGINFO_WORKS /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but this is not true on Solaris 8 at least. It doesn't hurt to use SA_NODEFER here, so leave it in. */ @@ -328,7 +318,7 @@ c_stack_action (void (*action) (int)) } #else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK - && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV) */ + && HAVE_STACK_OVERFLOW_HANDLING) || HAVE_LIBSIGSEGV) */ int c_stack_action (void (*action) (int) __attribute__ ((unused)))