Move to build-aux/config.guess.
[libsigsegv/ericb.git] / tests / stackoverflow2.c
blobf81de55845b3a8f3419c7b6a0a3eef94618a37be
1 /* Test that stack overflow and SIGSEGV are correctly distinguished.
2 Copyright (C) 2002-2005 Bruno Haible <bruno@clisp.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 #include "sigsegv.h"
19 #include <stdio.h>
20 #include <limits.h>
22 #if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGSEGV_RECOVERY
24 #if defined _WIN32 && !defined __CYGWIN__
25 /* Windows doesn't have sigset_t. */
26 typedef int sigset_t;
27 # define sigemptyset(set)
28 # define sigprocmask(how,set,oldset)
29 #else
30 /* Unix */
31 # include "config.h"
32 #endif
34 #include "mmaputil.h"
35 #include <stddef.h> /* needed for NULL on SunOS4 */
36 #include <stdlib.h> /* for abort, exit */
37 #include <signal.h>
38 #include <setjmp.h>
39 #if HAVE_SETRLIMIT
40 # include <sys/types.h>
41 # include <sys/time.h>
42 # include <sys/resource.h>
43 #endif
45 jmp_buf mainloop;
46 sigset_t mainsigset;
48 volatile int pass = 0;
49 unsigned long page;
51 void
52 stackoverflow_handler (int emergency, stackoverflow_context_t scp)
54 pass++;
55 if (pass <= 2)
56 printf ("Stack overflow %d caught.\n", pass);
57 else
59 printf ("Segmentation violation misdetected as stack overflow.\n");
60 exit (1);
62 sigprocmask (SIG_SETMASK, &mainsigset, NULL);
63 sigsegv_leave_handler ();
64 longjmp (mainloop, emergency ? -1 : pass);
67 int
68 sigsegv_handler (void *address, int emergency)
70 /* This test is necessary to distinguish stack overflow and SIGSEGV. */
71 if (!emergency)
72 return 0;
74 pass++;
75 if (pass <= 2)
77 printf ("Stack overflow %d missed.\n", pass);
78 exit (1);
80 else
81 printf ("Segmentation violation correctly detected.\n");
82 sigprocmask (SIG_SETMASK, &mainsigset, NULL);
83 sigsegv_leave_handler ();
84 longjmp (mainloop, pass);
87 volatile int *
88 recurse_1 (int n, volatile int *p)
90 if (n < INT_MAX)
91 *recurse_1 (n + 1, p) += n;
92 return p;
95 volatile int
96 recurse (volatile int n)
98 return *recurse_1 (n, (volatile int *) &n);
102 main ()
104 char mystack[16384];
105 sigset_t emptyset;
106 void *p;
108 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
109 /* Before starting the endless recursion, try to be friendly to the user's
110 machine. On some Linux 2.2.x systems, there is no stack limit for user
111 processes at all. We don't want to kill such systems. */
112 struct rlimit rl;
113 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
114 setrlimit (RLIMIT_STACK, &rl);
115 #endif
117 /* Install the stack overflow handler. */
118 if (stackoverflow_install_handler (&stackoverflow_handler,
119 mystack, sizeof (mystack))
120 < 0)
121 exit (2);
123 /* Preparations. */
124 #if !HAVE_MMAP_ANON && !HAVE_MMAP_ANONYMOUS && HAVE_MMAP_DEVZERO
125 zero_fd = open ("/dev/zero", O_RDONLY, 0644);
126 #endif
128 /* Setup some mmaped memory. */
129 p = mmap_zeromap ((void *) 0x12340000, 0x4000);
130 if (p == (void *)(-1))
132 fprintf (stderr, "mmap_zeromap failed.\n");
133 exit (2);
135 page = (unsigned long) p;
137 /* Make it read-only. */
138 if (mprotect ((void *) page, 0x4000, PROT_READ) < 0)
140 fprintf (stderr, "mprotect failed.\n");
141 exit (2);
144 /* Install the SIGSEGV handler. */
145 if (sigsegv_install_handler (&sigsegv_handler) < 0)
146 exit (2);
148 /* Save the current signal mask. */
149 sigemptyset (&emptyset);
150 sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
152 /* Provoke two stack overflows in a row. */
153 switch (setjmp (mainloop))
155 case -1:
156 printf ("emergency exit\n"); exit (1);
157 case 0: case 1:
158 printf ("Starting recursion pass %d.\n", pass + 1);
159 recurse (0);
160 printf ("no endless recursion?!\n"); exit (1);
161 case 2:
162 *(int *) (page + 0x678) = 42;
163 break;
164 case 3:
165 break;
166 default:
167 abort ();
170 printf ("Test passed.\n");
171 exit (0);
174 #else
177 main ()
179 return 77;
182 #endif