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