Bump to m4 1.4.19
[platform/upstream/m4.git] / tests / test-sigsegv-catch-segv1.c
1 /* Test that the handler is called, with the right fault address.
2    Copyright (C) 2002-2021  Bruno Haible <bruno@clisp.org>
3
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 of the License, or
7    (at your option) any later version.
8
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.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include "sigsegv.h"
21
22 #include <stdint.h>
23 #include <stdio.h>
24
25 #if HAVE_SIGSEGV_RECOVERY
26
27 # include "mmap-anon-util.h"
28 # include <stdlib.h>
29
30 # if SIGSEGV_FAULT_ADDRESS_ALIGNMENT > 1UL
31 #  include <unistd.h>
32 #  define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS (getpagesize () - 1)
33 # else
34 #  define SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS 0
35 # endif
36
37 uintptr_t page;
38
39 volatile int handler_called = 0;
40
41 int
42 handler (void *fault_address, int serious)
43 {
44   handler_called++;
45   if (handler_called > 10)
46     abort ();
47   if (fault_address
48       != (void *)((page + 0x678) & ~SIGSEGV_FAULT_ADDRESS_ROUNDOFF_BITS))
49     abort ();
50   if (mprotect ((void *) page, 0x4000, PROT_READ_WRITE) == 0)
51     return 1;
52   return 0;
53 }
54
55 void
56 crasher (uintptr_t p)
57 {
58   *(volatile int *) (p + 0x678) = 42;
59 }
60
61 int
62 main ()
63 {
64   int prot_unwritable;
65   void *p;
66
67   /* Preparations.  */
68 # if !HAVE_MAP_ANONYMOUS
69   zero_fd = open ("/dev/zero", O_RDONLY, 0644);
70 # endif
71
72 # if defined __linux__ && defined __sparc__
73   /* On Linux 2.6.26/SPARC64, PROT_READ has the same effect as
74      PROT_READ | PROT_WRITE.  */
75   prot_unwritable = PROT_NONE;
76 # else
77   prot_unwritable = PROT_READ;
78 # endif
79
80   /* Setup some mmaped memory.  */
81   p = mmap_zeromap ((void *) 0x12340000, 0x4000);
82   if (p == (void *)(-1))
83     {
84       fprintf (stderr, "mmap_zeromap failed.\n");
85       exit (2);
86     }
87   page = (uintptr_t) p;
88
89   /* Make it read-only.  */
90   if (mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
91     {
92       fprintf (stderr, "mprotect failed.\n");
93       exit (2);
94     }
95   /* Test whether it's possible to make it read-write after it was read-only.
96      This is not possible on Cygwin.  */
97   if (mprotect ((void *) page, 0x4000, PROT_READ_WRITE) < 0
98       || mprotect ((void *) page, 0x4000, prot_unwritable) < 0)
99     {
100       fprintf (stderr, "mprotect failed.\n");
101       exit (2);
102     }
103
104   /* Install the SIGSEGV handler.  */
105   sigsegv_install_handler (&handler);
106
107   /* The first write access should invoke the handler and then complete.  */
108   crasher (page);
109   /* The second write access should not invoke the handler.  */
110   crasher (page);
111
112   /* Check that the handler was called only once.  */
113   if (handler_called != 1)
114     exit (1);
115   /* Test passed!  */
116   printf ("Test passed.\n");
117   return 0;
118 }
119
120 #else
121
122 int
123 main ()
124 {
125   return 77;
126 }
127
128 #endif