summaryrefslogtreecommitdiffstats
path: root/src/common/ef/eftest.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/ef/eftest.c')
-rw-r--r--src/common/ef/eftest.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/common/ef/eftest.c b/src/common/ef/eftest.c
new file mode 100644
index 00000000..372ac596
--- /dev/null
+++ b/src/common/ef/eftest.c
@@ -0,0 +1,219 @@
+#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 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;
+}