NetBSD/dist/ntp/ElectricFence/eftest.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;
}