4 |
|
|
5 |
This program is free software; you can redistribute it and/or modify |
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 |
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) |
the Free Software Foundation; either version 2 of the License, or |
8 |
any later version. |
(at your option) any later version. |
9 |
|
|
10 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
15 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
16 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
17 |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 |
|
02110-1301 USA |
19 |
*/ |
*/ |
20 |
|
|
21 |
/* Compiled only when USE_STACKOVF is defined, which itself requires |
/* Compiled only when USE_STACKOVF is defined, which itself requires |
22 |
getrlimit with the RLIMIT_STACK option, and support for alternate |
getrlimit with the RLIMIT_STACK option, and support for alternate |
23 |
signal stacks using either SVR4 or BSD interfaces. |
signal stacks using either SVR4 or BSD interfaces. |
24 |
|
|
25 |
This should compile on ANY system which supports either sigaltstack() |
This should compile on ANY system which supports either sigaltstack() |
26 |
or sigstack(), with or without <siginfo.h> or another way to determine |
or sigstack(), with or without <siginfo.h> or another way to determine |
27 |
the fault address. |
the fault address. |
28 |
|
|
29 |
There is no completely portable way to determine if a SIGSEGV signal |
There is no completely portable way to determine if a SIGSEGV signal |
30 |
indicates a stack overflow. The fault address can be used to infer |
indicates a stack overflow. The fault address can be used to infer |
31 |
this. However, the fault address is passed to the signal handler in |
this. However, the fault address is passed to the signal handler in |
32 |
different ways on various systems. One of three methods are used to |
different ways on various systems. One of three methods are used to |
33 |
determine the fault address: |
determine the fault address: |
34 |
|
|
35 |
1. The siginfo parameter (with siginfo.h, i.e., SVR4). |
1. The siginfo parameter (with siginfo.h, i.e., SVR4). |
36 |
|
|
37 |
2. 4th "addr" parameter (assumed if struct sigcontext is defined, |
2. 4th "addr" parameter (assumed if struct sigcontext is defined, |
38 |
i.e., SunOS 4.x/BSD). |
i.e., SunOS 4.x/BSD). |
39 |
|
|
40 |
3. None (if no method is available). This case just prints a |
3. None (if no method is available). This case just prints a |
41 |
message before aborting with a core dump. That way the user at |
message before aborting with a core dump. That way the user at |
42 |
least knows that it *might* be a recursion problem. |
least knows that it *might* be a recursion problem. |
43 |
|
|
44 |
Jim Avera <jima@netcom.com> writes, on Tue, 5 Oct 93 19:27 PDT: |
Jim Avera <jima@netcom.com> writes, on Tue, 5 Oct 93 19:27 PDT: |
45 |
|
|
46 |
"I got interested finding out how a program could catch and |
"I got interested finding out how a program could catch and |
47 |
diagnose its own stack overflow, and ended up modifying m4 to do |
diagnose its own stack overflow, and ended up modifying m4 to do |
48 |
this. Now it prints a nice error message and exits. |
this. Now it prints a nice error message and exits. |
49 |
|
|
50 |
How it works: SIGSEGV is caught using a separate signal stack. The |
How it works: SIGSEGV is caught using a separate signal stack. The |
51 |
signal handler declares a stack overflow if the fault address is |
signal handler declares a stack overflow if the fault address is |
52 |
near the end of the stack region, or if the maximum VM address |
near the end of the stack region, or if the maximum VM address |
53 |
space limit has been reached. Otherwise, it returns to re-execute |
space limit has been reached. Otherwise, it returns to re-execute |
54 |
the instruction with SIG_DFL set, so that any real bugs cause a |
the instruction with SIG_DFL set, so that any real bugs cause a |
55 |
core dump as usual." |
core dump as usual." |
56 |
|
|
57 |
Jim Avera <jima@netcom.com> writes, on Fri, 24 Jun 94 12:14 PDT: |
Jim Avera <jima@netcom.com> writes, on Fri, 24 Jun 94 12:14 PDT: |
58 |
|
|
59 |
"The stack-overflow detection code would still be needed to avoid a |
"The stack-overflow detection code would still be needed to avoid a |
60 |
SIGSEGV abort if swap space was exhausted at the moment the stack |
SIGSEGV abort if swap space was exhausted at the moment the stack |
61 |
tried to grow. This is probably unlikely to occur with the |
tried to grow. This is probably unlikely to occur with the |
62 |
explicit nesting limit option of GNU m4." |
explicit nesting limit option of GNU m4." |
63 |
|
|
64 |
Jim Avera <jima@netcom.com> writes, on Wed, 6 Jul 1994 14:41 PDT: |
Jim Avera <jima@netcom.com> writes, on Wed, 6 Jul 1994 14:41 PDT: |
65 |
|
|
66 |
"When a stack overflow occurs, a SIGSEGV signal is sent, which by |
"When a stack overflow occurs, a SIGSEGV signal is sent, which by |
67 |
default aborts the process with a core dump. |
default aborts the process with a core dump. |
68 |
|
|
69 |
The code in stackovf.c catches SIGSEGV using a separate signal |
The code in stackovf.c catches SIGSEGV using a separate signal |
70 |
stack. The signal handler determines whether or not the SIGSEGV |
stack. The signal handler determines whether or not the SIGSEGV |
71 |
arose from a stack overflow. If it is a stack overflow, an |
arose from a stack overflow. If it is a stack overflow, an |
98 |
account for the maximum size of local variables (the amount the |
account for the maximum size of local variables (the amount the |
99 |
trapping reference might exceed the stack limit). Also, some machines |
trapping reference might exceed the stack limit). Also, some machines |
100 |
may report an arbitrary address within the same page frame. |
may report an arbitrary address within the same page frame. |
101 |
If the value is too large, we might call some other SIGSEGV a stack |
If the value is too large, we might call some other SIGSEGV a stack |
102 |
overflow, masking a bug. */ |
overflow, masking a bug. */ |
103 |
|
|
104 |
#ifndef STACKOVF_DETECT |
#ifndef STACKOVF_DETECT |
117 |
signal handler. The signal handler obtains information about the trap |
signal handler. The signal handler obtains information about the trap |
118 |
in an OS-dependent manner, and passes a parameter with the meanings as |
in an OS-dependent manner, and passes a parameter with the meanings as |
119 |
explained below. |
explained below. |
120 |
|
|
121 |
If the OS explicitly identifies a stack overflow trap, either pass |
If the OS explicitly identifies a stack overflow trap, either pass |
122 |
PARAM_STACKOVF if a stack overflow, or pass PARAM_NOSTACKOVF if not |
PARAM_STACKOVF if a stack overflow, or pass PARAM_NOSTACKOVF if not |
123 |
(id est, it is a random bounds violation). Otherwise, if the fault |
(id est, it is a random bounds violation). Otherwise, if the fault |
124 |
address is available, pass the fault address. Otherwise (if no |
address is available, pass the fault address. Otherwise (if no |
125 |
information is available), pass NULL. |
information is available), pass NULL. |
126 |
|
|
127 |
Not given an explicit indication, we compare the fault address with |
Not given an explicit indication, we compare the fault address with |
128 |
the estimated stack limit, and test to see if overall VM space is |
the estimated stack limit, and test to see if overall VM space is |
129 |
exhausted. |
exhausted. |
130 |
|
|
131 |
If a stack overflow is identified, then the external *stackovf_handler |
If a stack overflow is identified, then the external *stackovf_handler |
132 |
function is called, which should print an error message and exit. If |
function is called, which should print an error message and exit. If |
133 |
it is NOT a stack overflow, then we silently abort with a core dump by |
it is NOT a stack overflow, then we silently abort with a core dump by |
359 |
sigaction (SIGSEGV, NULL, &act); |
sigaction (SIGSEGV, NULL, &act); |
360 |
act.sa_handler = (RETSIGTYPE (*) _((int))) sigsegv_handler; |
act.sa_handler = (RETSIGTYPE (*) _((int))) sigsegv_handler; |
361 |
sigemptyset (&act.sa_mask); |
sigemptyset (&act.sa_mask); |
362 |
act.sa_flags = (SA_ONSTACK |
act.sa_flags = (SA_ONSTACK |
363 |
#ifdef SA_RESETHAND |
#ifdef SA_RESETHAND |
364 |
| SA_RESETHAND |
| SA_RESETHAND |
365 |
#endif |
#endif |
366 |
#ifdef SA_SIGINFO |
#ifdef SA_SIGINFO |
367 |
| SA_SIGINFO |
| SA_SIGINFO |
368 |
#endif |
#endif |
369 |
); |
); |
370 |
if (sigaction (SIGSEGV, &act, NULL) < 0) |
if (sigaction (SIGSEGV, &act, NULL) < 0) |