Initial progress in Issue #7 with support for a Dr. Fuzz harness.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user