Initial progress in Issue #7 with support for a Dr. Fuzz harness.

This commit is contained in:
Peter Goodman
2017-12-08 21:07:52 -05:00
parent a411f0e032
commit f9fb7e81be
2 changed files with 76 additions and 4 deletions

View File

@@ -24,6 +24,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <deepstate/Log.h>
#include <deepstate/Compiler.h>
@@ -37,6 +40,11 @@
#define assume DeepState_Assume
#define check DeepState_Check
#define MAYBE(...) \
if (DeepState_Bool()) { \
__VA_ARGS__ ; \
}
DEEPSTATE_BEGIN_EXTERN_C
/* Return a symbolic value of a given type. */
@@ -246,6 +254,9 @@ extern void DeepState_Setup(void);
/* Tear down DeepState. */
extern void DeepState_Teardown(void);
/* Notify that we're about to begin a test while running under Dr. Fuzz. */
extern void DeepState_BeginDrFuzz(struct DeepState_TestInfo *info);
/* Notify that we're about to begin a test. */
extern void DeepState_Begin(struct DeepState_TestInfo *info);
@@ -264,13 +275,21 @@ extern jmp_buf DeepState_ReturnToRun;
/* Start DeepState and run the tests. Returns the number of failed tests. */
static int DeepState_Run(void) {
int num_failed_tests = 0;
int use_drfuzz = getenv("DYNAMORIO_EXE_PATH") != NULL;
struct DeepState_TestInfo *test = NULL;
DeepState_Setup();
for (test = DeepState_FirstTest(); test != NULL; test = test->prev) {
DeepState_Begin(test);
if (use_drfuzz) {
if (!fork()) {
DeepState_BeginDrFuzz(test);
} else {
continue;
}
} else {
DeepState_Begin(test);
}
/* Run the test. */
if (!setjmp(DeepState_ReturnToRun)) {
@@ -305,6 +324,10 @@ static int DeepState_Run(void) {
}
}
if (use_drfuzz) {
waitpid(-1, NULL, 0); /* Wait for all children. */
}
DeepState_Teardown();
return num_failed_tests;

View File

@@ -26,6 +26,9 @@ DEEPSTATE_BEGIN_EXTERN_C
/* Pointer to the last registers DeepState_TestInfo data structure */
struct DeepState_TestInfo *DeepState_LastTestInfo = NULL;
/* Pointer to the test being run in this process by Dr. Fuzz. */
static struct DeepState_TestInfo *DeepState_DrFuzzTest = NULL;
enum {
DeepState_InputSize = 8192
};
@@ -193,7 +196,9 @@ int8_t DeepState_Char(void) {
#undef MAKE_SYMBOL_FUNC
void _DeepState_Assume(int expr) {
assert(expr);
if (!expr) {
DeepState_Abandon("");
}
}
int DeepState_IsSymbolicUInt(uint32_t x) {
@@ -271,7 +276,51 @@ void DeepState_Begin(struct DeepState_TestInfo *info) {
DeepState_TestFailed = 0;
DeepState_TestAbandoned = NULL;
DeepState_LogFormat(DeepState_LogInfo, "Running: %s from %s(%u)",
info->test_name, info->file_name, info->line_number);
info->test_name, info->file_name, info->line_number);
}
/* Runs in a child process, under the control of Dr. Memory */
void DrMemFuzzFunc(volatile uint8_t *buff, size_t size) {
struct DeepState_TestInfo *test = DeepState_DrFuzzTest;
DeepState_TestFailed = 0;
DeepState_InputIndex = 0;
DeepState_TestAbandoned = NULL;
DeepState_LogFormat(DeepState_LogInfo, "Running: %s from %s(%u)",
test->test_name, test->file_name, test->line_number);
if (!setjmp(DeepState_ReturnToRun)) {
/* Convert uncaught C++ exceptions into a test failure. */
#if defined(__cplusplus) && defined(__cpp_exceptions)
try {
#endif /* __cplusplus */
test->test_func();
DeepState_Pass();
#if defined(__cplusplus) && defined(__cpp_exceptions)
} catch(...) {
DeepState_Fail();
}
#endif /* __cplusplus */
/* We caught a failure when running the test. */
} else if (DeepState_CatchFail()) {
DeepState_LogFormat(DeepState_LogError, "Failed: %s", test->test_name);
/* The test was abandoned. We may have gotten soft failures before
* abandoning, so we prefer to catch those first. */
} else if (DeepState_CatchAbandoned()) {
DeepState_LogFormat(DeepState_LogFatal, "Abandoned: %s", test->test_name);
/* The test passed. */
} else {
DeepState_LogFormat(DeepState_LogInfo, "Passed: %s", test->test_name);
}
}
/* Notify that we're about to begin a test while running under Dr. Fuzz. */
void DeepState_BeginDrFuzz(struct DeepState_TestInfo *test) {
DeepState_DrFuzzTest = test;
DrMemFuzzFunc(DeepState_Input, DeepState_InputSize);
}
/* Return the first test case to run. */