This source file includes following definitions.
- stackoverflow_handler_continuation
- stackoverflow_handler
- sigsegv_handler
- recurse_1
- recurse
- main
- main
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 #include <config.h>
  20 
  21 
  22 #include "sigsegv.h"
  23 
  24 #include <stdint.h>
  25 #include <stdio.h>
  26 #include <limits.h>
  27 
  28 #if HAVE_STACK_OVERFLOW_RECOVERY && HAVE_SIGSEGV_RECOVERY
  29 
  30 # if defined _WIN32 && !defined __CYGWIN__
  31   
  32   typedef int sigset_t;
  33 #  define sigemptyset(set)
  34 #  define sigprocmask(how,set,oldset)
  35 # endif
  36 
  37 # include "mmap-anon-util.h"
  38 # include <stddef.h> 
  39 # include <stdlib.h> 
  40 # include <signal.h>
  41 # include <setjmp.h>
  42 # if HAVE_SETRLIMIT
  43 #  include <sys/types.h>
  44 #  include <sys/time.h>
  45 #  include <sys/resource.h>
  46 # endif
  47 # include "altstack-util.h"
  48 
  49 static jmp_buf mainloop;
  50 static sigset_t mainsigset;
  51 
  52 static volatile int pass = 0;
  53 static uintptr_t page;
  54 static volatile int *null_pointer_to_volatile_int ;
  55 
  56 static void
  57 stackoverflow_handler_continuation (void *arg1, void *arg2, void *arg3)
     
  58 {
  59   int arg = (int) (long) arg1;
  60   longjmp (mainloop, arg);
  61 }
  62 
  63 static void
  64 stackoverflow_handler (int emergency, stackoverflow_context_t scp)
     
  65 {
  66   pass++;
  67   if (pass <= 2)
  68     printf ("Stack overflow %d caught.\n", pass);
  69   else
  70     {
  71       printf ("Segmentation violation misdetected as stack overflow.\n");
  72       exit (1);
  73     }
  74   sigprocmask (SIG_SETMASK, &mainsigset, NULL);
  75   sigsegv_leave_handler (stackoverflow_handler_continuation,
  76                          (void *) (long) (emergency ? -1 : pass), NULL, NULL);
  77 }
  78 
  79 static int
  80 sigsegv_handler (void *address, int emergency)
     
  81 {
  82   
  83   if (!emergency)
  84     return 0;
  85 
  86   pass++;
  87   if (pass <= 2)
  88     {
  89       printf ("Stack overflow %d missed.\n", pass);
  90       exit (1);
  91     }
  92   else
  93     printf ("Segmentation violation correctly detected.\n");
  94   sigprocmask (SIG_SETMASK, &mainsigset, NULL);
  95   return sigsegv_leave_handler (stackoverflow_handler_continuation,
  96                                 (void *) (long) pass, NULL, NULL);
  97 }
  98 
  99 static volatile int *
 100 recurse_1 (int n, volatile int *p)
     
 101 {
 102   if (n < INT_MAX)
 103     *recurse_1 (n + 1, p) += n;
 104   return p;
 105 }
 106 
 107 static int
 108 recurse (volatile int n)
     
 109 {
 110   return *recurse_1 (n, &n);
 111 }
 112 
 113 int
 114 main ()
     
 115 {
 116   int prot_unwritable;
 117   void *p;
 118   sigset_t emptyset;
 119 
 120 # if HAVE_SETRLIMIT && defined RLIMIT_STACK
 121   
 122 
 123 
 124   struct rlimit rl;
 125   rl.rlim_cur = rl.rlim_max = 0x100000; 
 126   setrlimit (RLIMIT_STACK, &rl);
 127 # endif
 128 
 129   
 130   prepare_alternate_stack ();
 131 
 132   
 133   if (stackoverflow_install_handler (&stackoverflow_handler,
 134                                      mystack, MYSTACK_SIZE)
 135       < 0)
 136     exit (2);
 137 
 138   
 139 # if !HAVE_MAP_ANONYMOUS
 140   zero_fd = open ("/dev/zero", O_RDONLY, 0644);
 141 # endif
 142 
 143 # if defined __linux__ && defined __sparc__
 144   
 145 
 146   prot_unwritable = PROT_NONE;
 147 # else
 148   prot_unwritable = PROT_READ;
 149 # endif
 150 
 151   
 152   p = mmap_zeromap ((void *) 0x12340000, 0x4000);
 153   if (p == (void *)(-1))
 154     {
 155       fprintf (stderr, "mmap_zeromap failed.\n");
 156       exit (2);
 157     }
 158   page = (uintptr_t) p;
 159 
 160   
 161   if (mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
 162     {
 163       fprintf (stderr, "mprotect failed.\n");
 164       exit (2);
 165     }
 166 
 167   
 168   if (sigsegv_install_handler (&sigsegv_handler) < 0)
 169     exit (2);
 170 
 171   
 172   sigemptyset (&emptyset);
 173   sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
 174 
 175   
 176   switch (setjmp (mainloop))
 177     {
 178     case -1:
 179       printf ("emergency exit\n"); exit (1);
 180     case 0: case 1:
 181       printf ("Starting recursion pass %d.\n", pass + 1);
 182       recurse (0);
 183       printf ("no endless recursion?!\n"); exit (1);
 184     case 2:
 185       *(volatile int *) (page + 0x678) = 42;
 186       break;
 187     case 3:
 188       *null_pointer_to_volatile_int = 42;
 189       break;
 190     case 4:
 191       break;
 192     default:
 193       abort ();
 194     }
 195 
 196   
 197   check_alternate_stack_no_overflow ();
 198 
 199   printf ("Test passed.\n");
 200   exit (0);
 201 }
 202 
 203 #else
 204 
 205 int
 206 main ()
     
 207 {
 208   return 77;
 209 }
 210 
 211 #endif