| #include <utest/utest.h> | 
 | #include <errno.h> | 
 | #include <stdlib.h> | 
 | #include <stdio.h> | 
 | #include <math.h> | 
 | #include <limits.h> | 
 | #include <signal.h> | 
 | #include <pthread.h> | 
 | #include <setjmp.h> | 
 |  | 
 | TEST_SUITE("EFENCE"); | 
 |  | 
 | /* <--- Begin definition of test cases ---> */ | 
 |  | 
 | /* The guts of this test came from electric fence's tstheap: | 
 |  * | 
 |  *  Electric Fence - Red-Zone memory allocator. | 
 |  *  Bruce Perens, 1988, 1993 | 
 |  * | 
 |  *  For email below, drop spaces and <spam-buster> tag. | 
 |  *  MODIFIED:  March 20, 2014 (jric<spam-buster> @ <spam-buster> chegg DOT com) | 
 |  */ | 
 |  | 
 | #define	POOL_SIZE 1024 | 
 | #define	LARGEST_BUFFER 30000 | 
 | #define	TEST_DURATION 1000 | 
 |  | 
 | static void *pool[POOL_SIZE]; | 
 |  | 
 | bool test_alloc_and_free(void) | 
 | { | 
 | 	void **element; | 
 | 	size_t size; | 
 |  | 
 | 	for (int count = 0; count < TEST_DURATION; count++) { | 
 | 		element = &pool[(int)(drand48() * POOL_SIZE)]; | 
 | 		size = (size_t)(drand48() * (LARGEST_BUFFER + 1)); | 
 | 		if (*element) { | 
 | 			free(*element); | 
 | 			*element = 0; | 
 | 		} else if (size > 0) { | 
 | 			*element = malloc(size); | 
 | 			*(uint8_t*)(*element) = 0xab; | 
 | 			*(uint8_t*)(*element + size - 1) = 0xcd; | 
 | 		} | 
 | 	} | 
 | 	/* Surviving without page faulting is success. */ | 
 | 	return TRUE; | 
 | } | 
 |  | 
 | /* The pointer Needs to be volatile, so that blob = malloc() gets assigned | 
 |  * before the fault. */ | 
 | static char *volatile blob; | 
 | static jmp_buf save; | 
 | static void *fault_addr; | 
 |  | 
 | static void segv_action(int signr, siginfo_t *si, void *arg) | 
 | { | 
 | 	fault_addr = si->si_addr; | 
 | 	longjmp(save, 1); | 
 | } | 
 |  | 
 | static struct sigaction sigact = {.sa_sigaction = segv_action, 0}; | 
 |  | 
 | bool test_catching_fault(void) | 
 | { | 
 | 	pthread_yield();/* link in pth for intra-thread signals (SIGSEGV) */ | 
 | 	sigaction(SIGSEGV, &sigact, 0); | 
 | 	blob = malloc(PGSIZE); | 
 | 	if (!setjmp(save)) { | 
 | 		/* First time through, we'll try to pagefault. */ | 
 | 		blob[PGSIZE + 1] = 0; | 
 | 		UT_ASSERT_FMT("Tried to fault, but didn't!", FALSE); | 
 | 	} | 
 | 	/* Second time, we'll return via setjmp */ | 
 | 	UT_ASSERT_FMT("Fault addr was %p, should be %p", | 
 | 	              fault_addr == blob + PGSIZE + 1, fault_addr, | 
 | 	              blob + PGSIZE + 1); | 
 | 	return TRUE; | 
 | } | 
 |  | 
 | /* <--- End definition of test cases ---> */ | 
 |  | 
 | struct utest utests[] = { | 
 | 	UTEST_REG(alloc_and_free), | 
 | 	UTEST_REG(catching_fault), | 
 | }; | 
 | int num_utests = sizeof(utests) / sizeof(struct utest); | 
 |  | 
 | int main(int argc, char *argv[]) | 
 | { | 
 | 	char **whitelist = &argv[1]; | 
 | 	int whitelist_len = argc - 1; | 
 |  | 
 | 	RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len); | 
 | } |