X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fc-stack.c;h=7f0f488456eda1ca7aa91111573f1082de32a4be;hb=b24d8be2672089058c92924326da82a05a703d1d;hp=e5e3ab610dc5c45b0adfa9ec0ccd44bb4e494149;hpb=ae5dae6fd1caa993e969b869e42820a119385cbc;p=gnulib.git diff --git a/lib/c-stack.c b/lib/c-stack.c index e5e3ab610..7f0f48845 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-2011 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 @@ -46,9 +45,6 @@ #define _(msgid) gettext (msgid) #include -#ifndef ENOTSUP -# define ENOTSUP EINVAL -#endif #include #if ! HAVE_STACK_T && ! defined stack_t @@ -56,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,11 +77,12 @@ typedef struct sigaltstack stack_t; #include "c-stack.h" #include "exitfail.h" +#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 @@ -106,12 +109,18 @@ static 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; - write (STDERR_FILENO, program_name, strlen (program_name)); - write (STDERR_FILENO, ": ", 2); - write (STDERR_FILENO, message, strlen (message)); - write (STDERR_FILENO, "\n", 1); + ignore_value (write (STDERR_FILENO, program_name, strlen (program_name))); + ignore_value (write (STDERR_FILENO, ": ", 2)); + ignore_value (write (STDERR_FILENO, message, strlen (message))); + ignore_value (write (STDERR_FILENO, "\n", 1)); if (! signo) _exit (exit_failure); raise (signo); @@ -153,7 +162,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 { @@ -177,13 +186,13 @@ static void overflow_handler (int, stackoverflow_context_t) __attribute__ ((noreturn)); static 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 @@ -220,15 +229,17 @@ c_stack_action (void (*action) (int)) # if STACK_DIRECTION # define find_stack_direction(ptr) STACK_DIRECTION # else +# if ! SIGINFO_WORKS || HAVE_XSI_STACK_OVERFLOW_HEURISTIC static int find_stack_direction (char const *addr) { char dummy; return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1; } +# endif # endif -# if SIGACTION_WORKS +# if SIGINFO_WORKS /* Handle a segmentation violation and exit. This function is async-signal-safe. */ @@ -236,27 +247,27 @@ find_stack_direction (char const *addr) static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn)); static 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 (0 < info->si_code) - { # if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC - /* 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. - - 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 populates uc_stack with the details of the - interrupted stack, while Linux populates it with the details - of the current stack. */ - signo = 0; + /* 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. + + 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 populates uc_stack with the details of the + interrupted stack, while Linux populates it with the details + of the current stack. */ + signo = 0; # else + 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 end, 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; @@ -264,22 +275,22 @@ segv_handler (int signo, siginfo_t *info, size_t s = faulting_address - stack_base; size_t page_size = sysconf (_SC_PAGESIZE); if (find_stack_direction (NULL) < 0) - s += page_size; + s += page_size; if (s < stack_size + page_size) - signo = 0; + 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 -# endif } +# endif die (signo); } @@ -311,7 +322,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. */ @@ -330,7 +341,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)))