| #include "efence.h" | 
 | #include <setjmp.h> | 
 | #include <signal.h> | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <unistd.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 sigjmp_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); | 
 | 	siglongjmp(env, 1); | 
 | } | 
 |  | 
 | static int gotSegmentationFault(int (*test)(void)) | 
 | { | 
 | 	if (sigsetjmp(env, 1) == 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; | 
 | } |