Fix dup() of 9ns FDs
[akaros.git] / user / electric-fence / eftest.c
1 #include "efence.h"
2 #include <setjmp.h>
3 #include <signal.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 /*
10  * Electric Fence confidence tests.
11  * Make sure all of the various functions of Electric Fence work correctly.
12  */
13
14 #ifndef PAGE_PROTECTION_VIOLATED_SIGNAL
15 #define PAGE_PROTECTION_VIOLATED_SIGNAL SIGSEGV
16 #endif
17
18 struct diagnostic {
19         int (*test)(void);
20         int expectedStatus;
21         const char *explanation;
22 };
23
24 extern int EF_PROTECT_BELOW;
25 extern int EF_ALIGNMENT;
26
27 static sigjmp_buf env;
28
29 /*
30  * There is still too little standardization of the arguments and return
31  * type of signal handler functions.
32  */
33 static void segmentationFaultHandler(int signalNumber
34 #if (defined(_AIX))
35                                      ,
36                                      ...
37 #endif
38                                      )
39 {
40         signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
41         siglongjmp(env, 1);
42 }
43
44 static int gotSegmentationFault(int (*test)(void))
45 {
46         if (sigsetjmp(env, 1) == 0) {
47                 int status;
48
49                 signal(PAGE_PROTECTION_VIOLATED_SIGNAL, segmentationFaultHandler);
50                 status = (*test)();
51                 signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
52                 return status;
53         } else
54                 return 1;
55 }
56
57 static char *allocation;
58 /* c is global so that assignments to it won't be optimized out. */
59 char c;
60
61 static int testSizes(void)
62 {
63         /*
64          * If ef_number can't hold all of the bits of a void *, have the user
65          * add -DUSE_ LONG_LONG to the compiler flags so that ef_number will be
66          * declared as "unsigned long long" instead of "unsigned long".
67          */
68         return (sizeof(ef_number) < sizeof(void *));
69 }
70
71 static int allocateMemory(void)
72 {
73         allocation = (char *)malloc(1);
74
75         if (allocation != 0)
76                 return 0;
77         else
78                 return 1;
79 }
80
81 static int freeMemory(void)
82 {
83         free(allocation);
84         return 0;
85 }
86
87 static int protectBelow(void)
88 {
89         EF_PROTECT_BELOW = 1;
90         return 0;
91 }
92
93 static int read0(void)
94 {
95         c = *allocation;
96
97         return 0;
98 }
99
100 static int write0(void)
101 {
102         *allocation = 1;
103
104         return 0;
105 }
106
107 static int read1(void)
108 {
109         c = allocation[1];
110
111         return 0;
112 }
113
114 static int readMinus1(void)
115 {
116         c = allocation[-1];
117         return 0;
118 }
119
120 static struct diagnostic diagnostics[] = {
121     {testSizes, 0,
122      "Please add -DLONG_LONG to the compiler flags and recompile."},
123     {allocateMemory, 0,
124      "Allocation 1: This test allocates a single byte of memory."},
125     {read0, 0, "Read valid memory 1: This test reads the allocated memory."},
126     {write0, 0, "Write valid memory 1: This test writes the allocated memory."},
127     {read1, 1, "Read overrun: This test reads beyond the end of the buffer."},
128     {freeMemory, 0, "Free memory: This test frees the allocated memory."},
129     {protectBelow, 0,
130      "Protect below: This sets Electric Fence to protect\n"
131      "the lower boundary of a malloc buffer, rather than the\n"
132      "upper boundary."},
133     {allocateMemory, 0,
134      "Allocation 2: This allocates memory with the lower boundary"
135      " protected."},
136     {read0, 0, "Read valid memory 2: This test reads the allocated memory."},
137     {write0, 0, "Write valid memory 2: This test writes the allocated memory."},
138     {readMinus1, 1,
139      "Read underrun: This test reads before the beginning of the"
140      " buffer."},
141     {0, 0, 0}};
142
143 static const char failedTest[] = "Electric Fence confidence test failed.\n";
144
145 static const char newline = '\n';
146
147 int main(int argc, char **argv)
148 {
149         static const struct diagnostic *diag = diagnostics;
150
151         EF_PROTECT_BELOW = 0;
152         EF_ALIGNMENT = 0;
153
154         while (diag->explanation != 0) {
155                 int status = gotSegmentationFault(diag->test);
156
157                 if (status != diag->expectedStatus) {
158                         /*
159                          * Don't use stdio to print here, because stdio
160                          * uses malloc() and we've just proven that malloc()
161                          * is broken. Also, use _exit() instead of exit(),
162                          * because _exit() doesn't flush stdio.
163                          */
164                         write(2, failedTest, sizeof(failedTest) - 1);
165                         write(2, diag->explanation, strlen(diag->explanation));
166                         write(2, &newline, 1);
167                         _exit(-1);
168                 }
169                 diag++;
170         }
171         return 0;
172 }