blob: 09ce6470511a23ceac99979f8664a31425f6447d [file] [log] [blame]
#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);
}