From 6f1f648cd2e0e8a1ee3aead3d305bba3925a226e Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Thu, 27 Dec 2018 17:13:53 -0700 Subject: [PATCH 1/2] we can take over rand now --- src/include/deepstate/DeepState.h | 33 +++---------------------------- src/lib/DeepState.c | 33 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index b86b70cb..cd977cad 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -48,6 +48,8 @@ #define assume DeepState_Assume #define check DeepState_Check +#define rand DeepState_Int + #define MAYBE(...) \ if (DeepState_Bool()) { \ __VA_ARGS__ ; \ @@ -603,36 +605,7 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) { return DeepState_TestRunCrash; } -/* Run a test case with input initialized by fuzzing. */ -static enum DeepState_TestRunResult -DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test) { - DeepState_InputIndex = 0; - - for (int i = 0; i < DeepState_InputSize; i++) { - DeepState_Input[i] = (char)rand(); - } - - DeepState_Begin(test); - - enum DeepState_TestRunResult result = DeepState_ForkAndRunTest(test); - - if (result == DeepState_TestRunCrash) { - DeepState_LogFormat(DeepState_LogError, "Crashed: %s", test->test_name); - - if (HAS_FLAG_output_test_dir) { - DeepState_SaveCrashingTest(); - } - - DeepState_Crash(); - } - - if (FLAGS_abort_on_fail && ((result == DeepState_TestRunCrash) || - (result == DeepState_TestRunFail))) { - abort(); - } - - return result; -} +enum DeepState_TestRunResult DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test); /* Run a single saved test case with input initialized from the file * `name` in directory `dir`. */ diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 2871ecb1..3c05a18e 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -23,6 +23,8 @@ #include #include +#undef rand + DEEPSTATE_BEGIN_EXTERN_C DEFINE_uint(num_workers, 1, @@ -630,6 +632,37 @@ bool DeepState_CatchAbandoned(void) { return DeepState_CurrentTestRun->result == DeepState_TestRunAbandon; } +/* Run a test case with input initialized by fuzzing. + Has to be defined here since we redefine rand in the header. */ +enum DeepState_TestRunResult DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test) { + DeepState_InputIndex = 0; + + for (int i = 0; i < DeepState_InputSize; i++) { + DeepState_Input[i] = (char)rand(); + } + + DeepState_Begin(test); + + enum DeepState_TestRunResult result = DeepState_ForkAndRunTest(test); + + if (result == DeepState_TestRunCrash) { + DeepState_LogFormat(DeepState_LogError, "Crashed: %s", test->test_name); + + if (HAS_FLAG_output_test_dir) { + DeepState_SaveCrashingTest(); + } + + DeepState_Crash(); + } + + if (FLAGS_abort_on_fail && ((result == DeepState_TestRunCrash) || + (result == DeepState_TestRunFail))) { + abort(); + } + + return result; +} + extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size > sizeof(DeepState_Input)) { return 0; // Just ignore any too-big inputs From ead8c5cb9647e666427061fcc1b6982150188002 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Fri, 28 Dec 2018 19:25:47 -0700 Subject: [PATCH 2/2] warn people using srand --- src/include/deepstate/DeepState.h | 61 +++-------------------------- src/lib/DeepState.c | 64 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 56 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index cd977cad..73a91660 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -49,6 +49,7 @@ #define check DeepState_Check #define rand DeepState_Int +#define srand DeepState_Warn_srand #define MAYBE(...) \ if (DeepState_Bool()) { \ @@ -447,6 +448,8 @@ static bool DeepState_IsTestCaseFile(const char *name) { return false; } +extern void DeepState_Warn_srand(unsigned int seed); + /* Resets the global `DeepState_Input` buffer, then fills it with the * data found in the file `path`. */ static void DeepState_InitInputFromFile(const char *path) { @@ -605,7 +608,7 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) { return DeepState_TestRunCrash; } -enum DeepState_TestRunResult DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test); +extern enum DeepState_TestRunResult DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test); /* Run a single saved test case with input initialized from the file * `name` in directory `dir`. */ @@ -730,61 +733,7 @@ static int DeepState_RunSingleSavedTestCase(void) { return num_failed_tests; } -/* Fuzz test `FLAGS_input_which_test` or first test, if not defined. */ -static int DeepState_Fuzz(void) { - DeepState_LogFormat(DeepState_LogInfo, "Starting fuzzing"); - - if (HAS_FLAG_seed) { - srand(FLAGS_seed); - } else { - unsigned int seed = time(NULL); - DeepState_LogFormat(DeepState_LogWarning, "No seed provided; using %u", seed); - srand(seed); - } - - long start = (long)time(NULL); - long current = (long)time(NULL); - long diff = 0; - unsigned i = 0; - - int num_failed_tests = 0; - - struct DeepState_TestInfo *test = NULL; - - DeepState_Setup(); - - for (test = DeepState_FirstTest(); test != NULL; test = test->prev) { - if (HAS_FLAG_input_which_test) { - if (strncmp(FLAGS_input_which_test, test->test_name, strlen(FLAGS_input_which_test)) == 0) { - break; - } - } else { - DeepState_LogFormat(DeepState_LogInfo, - "No test specified, defaulting to last test defined"); - break; - } - } - - if (test == NULL) { - DeepState_LogFormat(DeepState_LogInfo, - "Could not find matching test for %s", - FLAGS_input_which_test); - return 0; - } - - while (diff < FLAGS_timeout) { - i++; - num_failed_tests += DeepState_FuzzOneTestCase(test); - - current = (long)time(NULL); - diff = current-start; - } - - DeepState_LogFormat(DeepState_LogInfo, "Ran %u tests. %d failed tests.", - i, num_failed_tests); - - return num_failed_tests; -} +extern int DeepState_Fuzz(void); /* Run tests from `FLAGS_input_test_files_dir`, under `FLAGS_input_which_test` * or first test, if not defined. */ diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 3c05a18e..b8445c20 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -24,6 +24,7 @@ #include #undef rand +#undef srand DEEPSTATE_BEGIN_EXTERN_C @@ -456,6 +457,11 @@ void DrMemFuzzFunc(volatile uint8_t *buff, size_t size) { } } +void DeepState_Warn_srand(unsigned int seed) { + DeepState_LogFormat(DeepState_LogWarning, + "srand under DeepState has no effect: rand is re-defined as DeepState_Int"); +} + void DeepState_RunSavedTakeOverCases(jmp_buf env, struct DeepState_TestInfo *test) { int num_failed_tests = 0; @@ -632,6 +638,64 @@ bool DeepState_CatchAbandoned(void) { return DeepState_CurrentTestRun->result == DeepState_TestRunAbandon; } +/* Fuzz test `FLAGS_input_which_test` or first test, if not defined. + Has to be defined here since we redefine rand in the header. */ +int DeepState_Fuzz(void){ + DeepState_LogFormat(DeepState_LogInfo, "Starting fuzzing"); + + if (HAS_FLAG_seed) { + srand(FLAGS_seed); + } else { + unsigned int seed = time(NULL); + DeepState_LogFormat(DeepState_LogWarning, "No seed provided; using %u", seed); + srand(seed); + } + + long start = (long)time(NULL); + long current = (long)time(NULL); + long diff = 0; + unsigned i = 0; + + int num_failed_tests = 0; + + struct DeepState_TestInfo *test = NULL; + + DeepState_Setup(); + + for (test = DeepState_FirstTest(); test != NULL; test = test->prev) { + if (HAS_FLAG_input_which_test) { + if (strncmp(FLAGS_input_which_test, test->test_name, strlen(FLAGS_input_which_test)) == 0) { + break; + } + } else { + DeepState_LogFormat(DeepState_LogInfo, + "No test specified, defaulting to last test defined"); + break; + } + } + + if (test == NULL) { + DeepState_LogFormat(DeepState_LogInfo, + "Could not find matching test for %s", + FLAGS_input_which_test); + return 0; + } + + while (diff < FLAGS_timeout) { + i++; + num_failed_tests += DeepState_FuzzOneTestCase(test); + + current = (long)time(NULL); + diff = current-start; + } + + DeepState_LogFormat(DeepState_LogInfo, "Ran %u tests. %d failed tests.", + i, num_failed_tests); + + return num_failed_tests; +} + + /* Run a test case with input initialized by fuzzing. Has to be defined here since we redefine rand in the header. */ enum DeepState_TestRunResult DeepState_FuzzOneTestCase(struct DeepState_TestInfo *test) {