222 lines
3.8 KiB
C
222 lines
3.8 KiB
C
/* $NetBSD: eftest.c,v 1.2 2003/12/04 16:23:34 drochner Exp $ */
|
|
|
|
#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;
|
|
}
|