stab at string generator

This commit is contained in:
Alex Groce 2018-12-30 12:26:43 -07:00
parent a0162e8242
commit 8a7b1c4faa
2 changed files with 73 additions and 1 deletions

View File

@ -139,9 +139,25 @@ DEEPSTATE_INLINE static int8_t DeepState_MaxChar(int8_t v) {
return (int8_t) DeepState_MaxInt(v);
}
/* Given a char pointer (assumed to have enough storage), places a string
* value in that location, with size characters (before null). If allowed is
* non-null, chooses characters from allowed char array. If null_terminated
* is true, the string will be null-terminated at size+1, and no prior character
* will be null. For null-terminated strings, storage must have space for the
* null terminator, so size should be 1 less than actual size. */
extern void DeepState_AssignString(char *dest, size_t max_size, const char* allowed,
size_t allowed_size, int null_terminated);
/* Returns a null-terminated string of size characters (before null), allocated on
* heap. DeepState will handle freeing these strings at termination of the test. */
extern char* DeepState_String(size_t max_size);
/* Function to clean up generated strings, and any other DeepState-managed data. */
extern void DeepState_CleanUp();
/* Returns `1` if `expr` is true, and `0` otherwise. This is kind of an indirect
* way to take a symbolic value, introduce a fork, and on each size, replace its
* value with a concrete value. */
* value with a concrete value. */
extern int DeepState_IsTrue(int expr);
/* Always returns `1`. */
@ -588,6 +604,7 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) {
test_pid = fork();
if (!test_pid) {
DeepState_RunTest(test);
/* No need to clean up in a fork; exit() is the ultimate garbage collector */
}
}
int wstatus = 0;
@ -595,6 +612,7 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) {
waitpid(test_pid, &wstatus, 0);
} else {
wstatus = DeepState_RunTestNoFork(test);
DeepState_CleanUp();
}
/* If we exited normally, the status code tells us if the test passed. */

View File

@ -54,6 +54,11 @@ int DeepState_UsingSymExec = 0;
/* Set to 1 when we're using libFuzzer. */
int DeepState_UsingLibFuzzer = 0;
/* Array of DeepState generated strings. Impossible for there to
* be more than there are input bytes. Index stores where we are. */
char* DeepState_GeneratedStrings[DeepState_InputSize];
uint32_t DeepState_GeneratedStringsIndex = 0;
/* Pointer to the last registers DeepState_TestInfo data structure */
struct DeepState_TestInfo *DeepState_LastTestInfo = NULL;
@ -311,6 +316,53 @@ int32_t DeepState_MaxInt(int32_t v) {
0x80000000U);
}
/* Given a char pointer (assumed to have enough storage), places a string
* value in that location, with size characters (before null). If allowed is
* non-null, chooses characters from allowed char array. If null_terminated
* is true, the string will be null-terminated at size+1, and no prior character
* will be null. For null-terminated strings, storage must have space for the
* null terminator, so size should be 1 less than actual size. */
void DeepState_AssignString(char *dest, size_t size, const char* allowed,
size_t allowed_size, int null_terminated) {
for(int i = 0; i < size; i++) {
if (allowed) {
size_t index = DeepState_UIntInRange(0, allowed_size);
dest[i] = allowed[index];
} else if (null_terminated) {
dest[i] = DeepState_UCharInRange(1, UCHAR_MAX); /* Disallow null termination till end. */
} else {
dest[i] = DeepState_UChar();
}
}
if (null_terminated) {
dest[size] = 0;
}
}
/* Returns a null-terminated string of size characters (before null), allocated on
* heap. DeepState will handle freeing these strings at termination of the test. */
char* DeepState_String(size_t size) {
char* rstr = malloc(size+1);
if (rstr) {
DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = rstr;
for (int i = 0; i < size; i++) {
rstr[i] = DeepState_UCharInRange(1, UCHAR_MAX); /* Disallow null termination till end. */
}
rstr[size] = 0;
} else {
DeepState_LogFormat(DeepState_LogFatal, "Unable to allocate to generate string!");
}
return rstr;
}
/* Function to clean up generated strings, and any other DeepState-managed data. */
extern void DeepState_CleanUp() {
for (int i = 0; i < DeepState_GeneratedStringsIndex; i++) {
free(DeepState_GeneratedStrings[i]);
}
DeepState_GeneratedStringsIndex = 0;
}
void _DeepState_Assume(int expr, const char *expr_str, const char *file,
unsigned line) {
if (!expr) {
@ -429,6 +481,7 @@ void DrMemFuzzFunc(volatile uint8_t *buff, size_t size) {
#endif /* __cplusplus */
test->test_func();
DeepState_CleanUp();
DeepState_Pass();
#if defined(__cplusplus) && defined(__cpp_exceptions)
@ -759,6 +812,7 @@ extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
DeepState_Begin(test);
enum DeepState_TestRunResult result = DeepState_RunTestNoFork(test);
DeepState_CleanUp();
const char* abort_check = getenv("LIBFUZZER_ABORT_ON_FAIL");
if (abort_check != NULL) {