Make c-stack use libsigsegv, when available.
[gnulib.git] / lib / c-stack.c
1 /* Stack overflow handling.
2
3    Copyright (C) 2002, 2004, 2006, 2008 Free Software Foundation, Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 /* Written by Paul Eggert.  */
19
20 /* NOTES:
21
22    A program that uses alloca, dynamic arrays, or large local
23    variables may extend the stack by more than a page at a time.  If
24    so, when the stack overflows the operating system may not detect
25    the overflow until the program uses the array, and this module may
26    incorrectly report a program error instead of a stack overflow.
27
28    To avoid this problem, allocate only small objects on the stack; a
29    program should be OK if it limits single allocations to a page or
30    less.  Allocate larger arrays in static storage, or on the heap
31    (e.g., with malloc).  Yes, this is a pain, but we don't know of any
32    better solution that is portable.
33
34    No attempt has been made to deal with multithreaded applications.  */
35
36 #include <config.h>
37
38 #ifndef __attribute__
39 # if __GNUC__ < 3
40 #  define __attribute__(x)
41 # endif
42 #endif
43
44 #include "gettext.h"
45 #define _(msgid) gettext (msgid)
46
47 #include <errno.h>
48 #ifndef ENOTSUP
49 # define ENOTSUP EINVAL
50 #endif
51
52 #include <signal.h>
53 #if ! HAVE_STACK_T && ! defined stack_t
54 typedef struct sigaltstack stack_t;
55 #endif
56 #ifndef SIGSTKSZ
57 # define SIGSTKSZ 16384
58 #endif
59
60 #include <stdlib.h>
61 #include <string.h>
62
63 /* Posix 2001 declares ucontext_t in <ucontext.h>, Posix 200x in
64    <signal.h>.  */
65 #if HAVE_UCONTEXT_H
66 # include <ucontext.h>
67 #endif
68
69 #include <unistd.h>
70 #ifndef STDERR_FILENO
71 # define STDERR_FILENO 2
72 #endif
73
74 #if HAVE_LIBSIGSEGV
75 # include <sigsegv.h>
76 #endif
77
78 #include "c-stack.h"
79 #include "exitfail.h"
80
81 #if defined SA_ONSTACK && defined SA_SIGINFO
82 # define SIGACTION_WORKS 1
83 #else
84 # define SIGACTION_WORKS 0
85 #endif
86
87 extern char *program_name;
88
89 /* The user-specified action to take when a SEGV-related program error
90    or stack overflow occurs.  */
91 static void (* volatile segv_action) (int);
92
93 /* Translated messages for program errors and stack overflow.  Do not
94    translate them in the signal handler, since gettext is not
95    async-signal-safe.  */
96 static char const * volatile program_error_message;
97 static char const * volatile stack_overflow_message;
98
99 /* Output an error message, then exit with status EXIT_FAILURE if it
100    appears to have been a stack overflow, or with a core dump
101    otherwise.  This function is async-signal-safe.  */
102
103 static void die (int) __attribute__ ((noreturn));
104 static void
105 die (int signo)
106 {
107   char const *message;
108   segv_action (signo);
109   message = signo ? program_error_message : stack_overflow_message;
110   write (STDERR_FILENO, program_name, strlen (program_name));
111   write (STDERR_FILENO, ": ", 2);
112   write (STDERR_FILENO, message, strlen (message));
113   write (STDERR_FILENO, "\n", 1);
114   if (! signo)
115     _exit (exit_failure);
116   raise (signo);
117   abort ();
118 }
119
120 #if (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV
121
122 /* Storage for the alternate signal stack.  */
123 static union
124 {
125   char buffer[SIGSTKSZ];
126
127   /* These other members are for proper alignment.  There's no
128      standard way to guarantee stack alignment, but this seems enough
129      in practice.  */
130   long double ld;
131   long l;
132   void *p;
133 } alternate_signal_stack;
134
135 static void
136 null_action (int signo __attribute__ ((unused)))
137 {
138 }
139
140 #endif /* SIGALTSTACK || LIBSIGSEGV */
141
142 /* Only use libsigsegv if we need it; platforms like Solaris can
143    detect stack overflow without the overhead of an external
144    library.  */
145 #if HAVE_LIBSIGSEGV && ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC
146
147 /* Nonzero if general segv handler could not be installed.  */
148 static volatile int segv_handler_missing;
149
150 /* Handle a segmentation violation and exit if it cannot be stack
151    overflow.  This function is async-signal-safe.  */
152
153 static int segv_handler (void *address __attribute__ ((unused)),
154                          int serious)
155 {
156 # if DEBUG
157   {
158     char buf[1024];
159     sprintf (buf, "segv_handler serious=%d\n", serious);
160     write (STDERR_FILENO, buf, strlen (buf));
161   }
162 # endif
163
164   /* If this fault is not serious, return 0 to let the stack overflow
165      handler take a shot at it.  */
166   if (!serious)
167     return 0;
168   die (SIGSEGV);
169 }
170
171 /* Handle a segmentation violation that is likely to be a stack
172    overflow and exit.  This function is async-signal-safe.  */
173
174 static void overflow_handler (int, stackoverflow_context_t)
175   __attribute__ ((noreturn));
176 static void
177 overflow_handler (int emergency,
178                   stackoverflow_context_t context __attribute__ ((unused)))
179 {
180 # if DEBUG
181   {
182     char buf[1024];
183     sprintf (buf, "overflow_handler emergency=%d segv_handler_missing=%d\n",
184              emergency, segv_handler_missing);
185     write (STDERR_FILENO, buf, strlen (buf));
186   }
187 # endif
188
189   die ((!emergency || segv_handler_missing) ? 0 : SIGSEGV);
190 }
191
192 /* Set up ACTION so that it is invoked on C stack overflow.  Return -1
193    (setting errno) if this cannot be done.
194
195    When ACTION is called, it is passed an argument equal to SIGSEGV
196    for a segmentation violation that does not appear related to stack
197    overflow, and is passed zero otherwise.  On many platforms it is
198    hard to tell; when in doubt, zero is passed.
199
200    A null ACTION acts like an action that does nothing.
201
202    ACTION must be async-signal-safe.  ACTION together with its callees
203    must not require more than SIGSTKSZ bytes of stack space.  Also,
204    ACTION should not call longjmp, because this implementation does
205    not guarantee that it is safe to return to the original stack.  */
206
207 int
208 c_stack_action (void (*action) (int))
209 {
210   segv_action = action ? action : null_action;
211   program_error_message = _("program error");
212   stack_overflow_message = _("stack overflow");
213
214   /* Always install the overflow handler.  */
215   if (stackoverflow_install_handler (overflow_handler,
216                                      alternate_signal_stack.buffer,
217                                      sizeof alternate_signal_stack.buffer))
218     {
219       errno = ENOTSUP;
220       return -1;
221     }
222   /* Try installing a general handler; if it fails, then treat all
223      segv as stack overflow.  */
224   segv_handler_missing = sigsegv_install_handler (segv_handler);
225   return 0;
226 }
227
228 #elif HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK
229
230 /* Direction of the C runtime stack.  This function is
231    async-signal-safe.  */
232
233 # if STACK_DIRECTION
234 #  define find_stack_direction(ptr) STACK_DIRECTION
235 # else
236 static int
237 find_stack_direction (char const *addr)
238 {
239   char dummy;
240   return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1;
241 }
242 # endif
243
244 # if SIGACTION_WORKS
245
246 /* Handle a segmentation violation and exit.  This function is
247    async-signal-safe.  */
248
249 static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn));
250 static void
251 segv_handler (int signo, siginfo_t *info,
252               void *context __attribute__ ((unused)))
253 {
254   /* Clear SIGNO if it seems to have been a stack overflow.  */
255   if (0 < info->si_code)
256     {
257 #  if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC
258       /* We can't easily determine whether it is a stack overflow; so
259          assume that the rest of our program is perfect (!) and that
260          this segmentation violation is a stack overflow.
261
262          Note that although both Linux and Solaris provide
263          sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only
264          Solaris satisfies the XSI heueristic.  This is because
265          Solaris populates uc_stack with the details of the
266          interrupted stack, while Linux populates it with the details
267          of the current stack.  */
268       signo = 0;
269 #  else
270       /* If the faulting address is within the stack, or within one
271          page of the stack end, assume that it is a stack
272          overflow.  */
273       ucontext_t const *user_context = context;
274       char const *stack_base = user_context->uc_stack.ss_sp;
275       size_t stack_size = user_context->uc_stack.ss_size;
276       char const *faulting_address = info->si_addr;
277       size_t s = faulting_address - stack_base;
278       size_t page_size = sysconf (_SC_PAGESIZE);
279       if (find_stack_direction (NULL) < 0)
280         s += page_size;
281       if (s < stack_size + page_size)
282         signo = 0;
283
284 #   if DEBUG
285       {
286         char buf[1024];
287         sprintf (buf,
288                  "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n",
289                  faulting_address, stack_base, (unsigned long) stack_size,
290                  (unsigned long) page_size, signo);
291         write (STDERR_FILENO, buf, strlen (buf));
292       }
293 #   endif
294 #  endif
295     }
296
297   die (signo);
298 }
299 # endif
300
301 /* Set up ACTION so that it is invoked on C stack overflow.  Return -1
302    (setting errno) if this cannot be done.
303
304    When ACTION is called, it is passed an argument equal to SIGSEGV
305    for a segmentation violation that does not appear related to stack
306    overflow, and is passed zero otherwise.  On many platforms it is
307    hard to tell; when in doubt, zero is passed.
308
309    A null ACTION acts like an action that does nothing.
310
311    ACTION must be async-signal-safe.  ACTION together with its callees
312    must not require more than SIGSTKSZ bytes of stack space.  Also,
313    ACTION should not call longjmp, because this implementation does
314    not guarantee that it is safe to return to the original stack.  */
315
316 int
317 c_stack_action (void (*action) (int))
318 {
319   int r;
320   stack_t st;
321   struct sigaction act;
322   st.ss_flags = 0;
323   st.ss_sp = alternate_signal_stack.buffer;
324   st.ss_size = sizeof alternate_signal_stack.buffer;
325   r = sigaltstack (&st, NULL);
326   if (r != 0)
327     return r;
328
329   segv_action = action ? action : null_action;
330   program_error_message = _("program error");
331   stack_overflow_message = _("stack overflow");
332
333   sigemptyset (&act.sa_mask);
334
335 # if SIGACTION_WORKS
336   /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but
337      this is not true on Solaris 8 at least.  It doesn't hurt to use
338      SA_NODEFER here, so leave it in.  */
339   act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
340   act.sa_sigaction = segv_handler;
341 # else
342   act.sa_flags = SA_NODEFER | SA_RESETHAND;
343   act.sa_handler = die;
344 # endif
345
346   return sigaction (SIGSEGV, &act, NULL);
347 }
348
349 #else /* ! ((HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) || HAVE_LIBSIGSEGV) */
350
351 int
352 c_stack_action (void (*action) (int)  __attribute__ ((unused)))
353 {
354   errno = ENOTSUP;
355   return -1;
356 }
357
358 #endif