095f890e514209ddcc3f4b1e4d270c55b4d2c09c
[gnulib.git] / lib / c-stack.c
1 /* Stack overflow handling.
2
3    Copyright (C) 2002 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 2, or (at your option)
8    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, write to the Free Software Foundation,
17    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 /* Written by Paul Eggert.  */
20
21 /* NOTES:
22
23    A program that uses alloca, dynamic arrays, or large local
24    variables may extend the stack by more than a page at a time.  If
25    so, when the stack overflows the operating system may not detect
26    the overflow until the program uses the array, and this module may
27    incorrectly report a program error instead of a stack overflow.
28
29    To avoid this problem, allocate only small objects on the stack; a
30    program should be OK if it limits single allocations to a page or
31    less.  Allocate larger arrays in static storage, or on the heap
32    (e.g., with malloc).  Yes, this is a pain, but we don't know of any
33    better solution that is portable.
34
35    No attempt has been made to deal with multithreaded applications.
36
37    If ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC, the current implementation
38    assumes that, if the RLIMIT_STACK limit changes during execution,
39    then c_stack_action is invoked immediately afterwards.  */
40
41 #if HAVE_CONFIG_H
42 # include <config.h>
43 #endif
44
45 #ifndef __attribute__
46 # if __GNUC__ < 3 || __STRICT_ANSI__
47 #  define __attribute__(x)
48 # endif
49 #endif
50
51 #include "gettext.h"
52 #define _(msgid) gettext (msgid)
53
54 #include <errno.h>
55 #ifndef ENOTSUP
56 # define ENOTSUP EINVAL
57 #endif
58 #ifndef EOVERFLOW
59 # define EOVERFLOW EINVAL
60 #endif
61
62 #include <signal.h>
63 #if ! HAVE_STACK_T && ! defined stack_t
64 typedef struct sigaltstack stack_t;
65 #endif
66
67 #include <stdlib.h>
68 #include <string.h>
69
70 #if HAVE_SYS_RESOURCE_H
71 # include <sys/resource.h>
72 #endif
73
74 #if HAVE_UCONTEXT_H
75 # include <ucontext.h>
76 #endif
77
78 #if HAVE_UNISTD_H
79 # include <unistd.h>
80 #endif
81 #ifndef STDERR_FILENO
82 # define STDERR_FILENO 2
83 #endif
84
85 #if DEBUG
86 # include <stdio.h>
87 #endif
88
89 #include "c-stack.h"
90 #include "exitfail.h"
91
92 extern char *program_name;
93
94 /* The user-specified action to take when a SEGV-related program error
95    or stack overflow occurs.  */
96 static void (* volatile segv_action) (int);
97
98 /* Translated messages for program errors and stack overflow.  Do not
99    translate them in the signal handler, since gettext is not
100    async-signal-safe.  */
101 static char const * volatile program_error_message;
102 static char const * volatile stack_overflow_message;
103
104 /* Output an error message, then exit with status EXIT_FAILURE if it
105    appears to have been a stack overflow, or with a core dump
106    otherwise.  This function is async-signal-safe.  */
107
108 static void die (int) __attribute__ ((noreturn));
109 static void
110 die (int signo)
111 {
112   char const *message =
113     signo ? program_error_message : stack_overflow_message;
114   segv_action (signo);
115   write (STDERR_FILENO, program_name, strlen (program_name));
116   write (STDERR_FILENO, ": ", 2);
117   write (STDERR_FILENO, message, strlen (message));
118   write (STDERR_FILENO, "\n", 1);
119   if (! signo)
120     _exit (exit_failure);
121   kill (getpid (), signo);
122   abort ();
123 }
124
125 #if HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK
126
127 /* Direction of the C runtime stack.  This function is
128    async-signal-safe.  */
129
130 # if STACK_DIRECTION
131 #  define find_stack_direction(ptr) STACK_DIRECTION
132 # else
133 static int
134 find_stack_direction (char const *addr)
135 {
136   char dummy;
137   return ! addr ? find_stack_direction (&dummy) : addr < &dummy ? 1 : -1;
138 }
139 # endif
140
141 # if HAVE_XSI_STACK_OVERFLOW_HEURISTIC
142 #  define get_stack_location(argv) 0
143 # else
144
145 #  if defined RLIMIT_STACK && defined _SC_PAGESIZE
146
147 /* Return the minimum machine address deducible from ARGV.  This
148    includes the addresses of all the strings that ARGV points at, as
149    well as the address of ARGV itself.  */
150
151 static char const *
152 min_address_from_argv (char * const *argv)
153 {
154   char const *min = (char const *) argv;
155   char const *p;
156   while ((p = *argv++))
157     if (p < min)
158       min = p;
159   return min;
160 }
161
162 /* Return the maximum machine address deducible from ARGV.  */
163
164 static char const *
165 max_address_from_argv (char * const *argv)
166 {
167   char const *max = *argv;
168   char const *max1;
169   char const *p;
170   while ((p = *argv++))
171     if (max < p)
172       max = p;
173   max1 = (char const *) (argv + 1);
174   return max && max1 < max ? max + strlen (max) + 1 : max1;
175 }
176 #  endif
177
178 /* The base and size of the stack, determined at startup.  */
179 static char const * volatile stack_base;
180 static size_t volatile stack_size;
181
182 /* Store the base and size of the stack into the static variables
183    STACK_BASE and STACK_SIZE.  The base is the numerically lowest
184    address in the stack.  Return -1 (setting errno) if this cannot be
185    done.  */
186
187 static int
188 get_stack_location (char * const *argv)
189 {
190 #  if ! (defined RLIMIT_STACK && defined _SC_PAGESIZE)
191
192   errno = ENOTSUP;
193   return -1;
194
195 #  else
196
197   struct rlimit rlimit;
198   int r = getrlimit (RLIMIT_STACK, &rlimit);
199   if (r == 0)
200     {
201       char const *base;
202       size_t size = rlimit.rlim_cur;
203       extern char **environ;
204       size_t page_size = sysconf (_SC_PAGESIZE);
205       int stack_direction = find_stack_direction (0);
206
207 #   if HAVE_GETCONTEXT && HAVE_DECL_GETCONTEXT
208       ucontext_t context;
209       if (getcontext (&context) == 0)
210         {
211           base = context.uc_stack.ss_sp;
212           if (stack_direction < 0)
213             base -= size - context.uc_stack.ss_size;
214         }
215       else
216 #   endif
217         {
218           if (stack_direction < 0)
219             {
220               char const *a = max_address_from_argv (argv);
221               char const *b = max_address_from_argv (environ);
222               base = (a < b ? b : a) - size;
223               base += - (size_t) base % page_size;
224             }
225           else
226             {
227               char const *a = min_address_from_argv (argv);
228               char const *b = min_address_from_argv (environ);
229               base = a < b ? a : b;
230               base -= (size_t) base % page_size;
231             }
232         }
233
234       if (size != rlimit.rlim_cur
235           || rlimit.rlim_cur < 0
236           || base + size < base
237 #   ifdef RLIM_SAVED_CUR
238           || rlimit.rlim_cur == RLIM_SAVED_CUR
239 #   endif
240 #   ifdef RLIM_SAVED_MAX
241           || rlimit.rlim_cur == RLIM_SAVED_MAX
242 #   endif
243 #   ifdef RLIM_INFINITY
244           || rlimit.rlim_cur == RLIM_INFINITY
245 #   endif
246           )
247         {
248           errno = EOVERFLOW;
249           return -1;
250         }
251
252       stack_base = base;
253       stack_size = size;
254
255 #   if DEBUG
256       fprintf (stderr, "get_stack_location base=%p size=%lx\n",
257                base, (unsigned long) size);
258 #   endif
259     }
260
261   return r;
262
263 #  endif
264 }
265 # endif
266
267 /* Storage for the alternate signal stack.  */
268 static union
269 {
270   char buffer[SIGSTKSZ];
271
272   /* These other members are for proper alignment.  There's no
273      standard way to guarantee stack alignment, but this seems enough
274      in practice.  */
275   long double ld;
276   long l;
277   void *p;
278 } alternate_signal_stack;
279
280 # if defined SA_ONSTACK && defined SA_SIGINFO && defined _SC_PAGESIZE
281
282 /* Handle a segmentation violation and exit.  This function is
283    async-signal-safe.  */
284
285 static void segv_handler (int, siginfo_t *, void *) __attribute__((noreturn));
286 static void
287 segv_handler (int signo, siginfo_t *info,
288               void *context __attribute__ ((unused)))
289 {
290   /* Clear SIGNO if it seems to have been a stack overflow.  */
291   if (0 < info->si_code)
292     {
293       /* If the faulting address is within the stack, or within one
294          page of the stack end, assume that it is a stack
295          overflow.  */
296 #  if HAVE_XSI_STACK_OVERFLOW_HEURISTIC
297       ucontext_t const *user_context = context;
298       char const *stack_base = user_context->uc_stack.ss_sp;
299       size_t stack_size = user_context->uc_stack.ss_size;
300 #  endif
301       char const *faulting_address = info->si_addr;
302       size_t s = faulting_address - stack_base;
303       size_t page_size = sysconf (_SC_PAGESIZE);
304       if (find_stack_direction (0) < 0)
305         s += page_size;
306       if (s < stack_size + page_size)
307         signo = 0;
308
309 #  if DEBUG
310       {
311         char buf[1024];
312         sprintf (buf,
313                  "segv_handler fault=%p base=%p size=%lx page=%lx signo=%d\n",
314                  faulting_address, stack_base, (unsigned long) stack_size,
315                  (unsigned long) page_size, signo);
316         write (STDERR_FILENO, buf, strlen (buf));
317       }
318 #  endif
319     }
320
321   die (signo);
322 }
323 # endif
324
325 static void
326 null_action (int signo __attribute__ ((unused)))
327 {
328 }
329
330 /* Assuming ARGV is the argument vector of `main', set up ACTION so
331    that it is invoked on C stack overflow.  Return -1 (setting errno)
332    if this cannot be done.
333
334    When ACTION is called, it is passed an argument equal to SIGSEGV
335    for a segmentation violation that does not appear related to stack
336    overflow, and is passed zero otherwise.
337
338    A null ACTION acts like an action that does nothing.
339
340    ACTION must be async-signal-safe.  ACTION together with its callees
341    must not require more than SIGSTKSZ bytes of stack space.  */
342
343 int
344 c_stack_action (char * const *argv __attribute__ ((unused)),
345                 void (*action) (int))
346 {
347   int r = get_stack_location (argv);
348   if (r != 0)
349     return r;
350
351   {
352     stack_t st;
353     st.ss_flags = 0;
354     st.ss_sp = alternate_signal_stack.buffer;
355     st.ss_size = sizeof alternate_signal_stack.buffer;
356     r = sigaltstack (&st, 0);
357     if (r != 0)
358       return r;
359   }
360
361   segv_action = action ? action : null_action;
362   program_error_message = _("program error");
363   stack_overflow_message = _("stack overflow");
364
365   {
366 # if ! (defined SA_ONSTACK && defined SA_SIGINFO && defined _SC_PAGESIZE)
367     return signal (SIGSEGV, die) == SIG_ERR ? -1 : 0;
368 # else
369     struct sigaction act;
370     sigemptyset (&act.sa_mask);
371
372     /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but
373        this is not true on Solaris 8 at least.  It doesn't hurt to use
374        SA_NODEFER here, so leave it in.  */
375     act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
376
377     act.sa_sigaction = segv_handler;
378
379     return sigaction (SIGSEGV, &act, 0);
380 # endif
381   }
382 }
383
384 #else /* ! (HAVE_SIGALTSTACK && HAVE_DECL_SIGALTSTACK) */
385
386 int
387 c_stack_action (char * const *argv __attribute__ ((unused)),
388                 void (*action) (int)  __attribute__ ((unused)))
389 {
390   errno = ENOTSUP;
391   return -1;
392 }
393
394 #endif
395
396 \f
397
398 #if DEBUG
399
400 int volatile exit_failure;
401
402 static long
403 recurse (char *p)
404 {
405   char array[500];
406   array[0] = 1;
407   return *p + recurse (array);
408 }
409
410 char *program_name;
411
412 int
413 main (int argc __attribute__ ((unused)), char **argv)
414 {
415   program_name = argv[0];
416   fprintf (stderr, "The last line of output should be \"stack overflow\".\n");
417   if (c_stack_action (argv, 0) == 0)
418     return recurse ("\1");
419   perror ("c_stack_action");
420   return 1;
421 }
422
423 #endif /* DEBUG */
424 \f
425 /*
426 Local Variables:
427 compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W c-stack.c"
428 End:
429 */