From 8a7b1c4faa8e9406983ae9355a440d3b2cefef0f Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Sun, 30 Dec 2018 12:26:43 -0700 Subject: [PATCH 01/39] stab at string generator --- src/include/deepstate/DeepState.h | 20 +++++++++++- src/lib/DeepState.c | 54 +++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 73a9166..aa57282 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -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. */ diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index b8445c2..425e80a 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -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) { From dee5dd549cbf3e282e2603ca1d303759fff7f1df Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Sun, 30 Dec 2018 21:04:15 -0700 Subject: [PATCH 02/39] C++ functions that also vary string length, using Pump --- src/include/deepstate/DeepState.h | 4 ++-- src/include/deepstate/DeepState.hpp | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index aa57282..5a33970 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -145,12 +145,12 @@ DEEPSTATE_INLINE static int8_t DeepState_MaxChar(int8_t v) { * 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, +extern void DeepState_AssignString(char *dest, size_t 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); +extern char* DeepState_String(size_t size); /* Function to clean up generated strings, and any other DeepState-managed data. */ extern void DeepState_CleanUp(); diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index e4c0617..03d14c2 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -314,7 +314,7 @@ static T Pump(T val, unsigned max=10) { } return Minimize(val); } - + template inline static void ForAll(void (*func)(Args...)) { func(Symbolic()...); @@ -345,7 +345,7 @@ inline static char OneOf(const char *str) { } return str[DeepState_IntInRange(0, strlen(str) - 1)]; } - + template inline static const T &OneOf(const std::vector &arr) { if (arr.empty()) { @@ -471,6 +471,25 @@ struct Comparer { } }; +/* Given a char pointer (assumed to have enough storage), places a C string + * value in that location, with up to max_size characters (strlen, not counting + * 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 max_size should be 1 less than actual size. */ +inline static void DeepState_AssignCString(char *dest, size_t max_size, const char* allowed, + size_t allowed_size, int null_terminated) { + uint32_t size = DeepState_UIntInRange(0, max_size); + DeepState_AssignString(dest, Pump(size, max_size), allowed, allowed_size, null_terminated); +} + +/* Returns a null-terminated C string of up to max_size characters (strlen), allocated on + * heap. DeepState will handle freeing these strings at termination of the test. */ +inline static char* DeepState_CString(size_t max_size) { + uint32_t size = DeepState_UIntInRange(0, max_size); + return DeepState_String(Pump(size, max_size)); +} + } // namespace deepstate #define ONE_OF ::deepstate::OneOf From 58a1d5120d6fb84bc18dea380cb77c670bb7fa06 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 08:02:09 -0700 Subject: [PATCH 03/39] new string functions --- src/include/deepstate/DeepState.h | 18 +++------- src/include/deepstate/DeepState.hpp | 24 +++++-------- src/lib/DeepState.c | 55 +++++++++-------------------- 3 files changed, 30 insertions(+), 67 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 5a33970..6838ac4 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -139,19 +139,6 @@ 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 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 size); - /* Function to clean up generated strings, and any other DeepState-managed data. */ extern void DeepState_CleanUp(); @@ -176,6 +163,11 @@ extern void DeepState_SymbolizeData(void *begin, void *end); * concrete pointer to the beginning of the concretized data. */ extern void *DeepState_ConcretizeData(void *begin, void *end); +/* Assign a symbolic C string of length `len` with only chars in allowed, + * if allowed is non-null */ +extern void DeepState_AssignCStr(char* str, size_t len, const char* allowed, + size_t allowed_size); + /* Return a symbolic C string of length `len`. */ extern char *DeepState_CStr(size_t len); diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 03d14c2..d9f148d 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -471,23 +471,17 @@ struct Comparer { } }; -/* Given a char pointer (assumed to have enough storage), places a C string - * value in that location, with up to max_size characters (strlen, not counting - * 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 max_size should be 1 less than actual size. */ -inline static void DeepState_AssignCString(char *dest, size_t max_size, const char* allowed, - size_t allowed_size, int null_terminated) { - uint32_t size = DeepState_UIntInRange(0, max_size); - DeepState_AssignString(dest, Pump(size, max_size), allowed, allowed_size, null_terminated); +/* Like DeepState_AssignCStr, but Pumps through possible string sizes. */ +inline static void DeepState_AssignCStrMax(char* str, size_t max_len, const char* allowed, + size_t allowed_size) { + uint32_t size = DeepState_UIntInRange(0, max_len); + DeepState_AssignCStr(str, Pump(size, max_len), allowed, allowed_size); } -/* Returns a null-terminated C string of up to max_size characters (strlen), allocated on - * heap. DeepState will handle freeing these strings at termination of the test. */ -inline static char* DeepState_CString(size_t max_size) { - uint32_t size = DeepState_UIntInRange(0, max_size); - return DeepState_String(Pump(size, max_size)); +/* Like DeepState_CStr, but Pumps through possible string sizes. */ +inline static char* DeepState_CStrMax(size_t max_len) { + uint32_t size = DeepState_UIntInRange(0, max_len); + return DeepState_CStr(Pump(size, max_len)); } } // namespace deepstate diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 425e80a..6f2860a 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -175,6 +175,21 @@ void *DeepState_ConcretizeData(void *begin, void *end) { return begin; } +/* Assign a symbolic C string of length `len`. */ +void DeepState_AssignCStr(char* str, size_t len, const char* allowed, + size_t allowed_size) { + if (SIZE_MAX == len) { + DeepState_Abandon("Can't create an SIZE_MAX-length string."); + } + if (NULL == str) { + DeepState_Abandon("Attempted to populate null pointer."); + } + for (int i = 0; i < len; i++) { + str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + } + str[len] = '\0'; +} + /* Return a symbolic C string of length `len`. */ char *DeepState_CStr(size_t len) { if (SIZE_MAX == len) { @@ -184,6 +199,7 @@ char *DeepState_CStr(size_t len) { if (NULL == str) { DeepState_Abandon("Can't allocate memory."); } + DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = str; if (len) { DeepState_SymbolizeData(str, &(str[len - 1])); } @@ -316,45 +332,6 @@ 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++) { From abba98ad2a0788d4903930f48c37ce14ebf00fde Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 08:12:03 -0700 Subject: [PATCH 04/39] no need for allowed length --- src/include/deepstate/DeepState.h | 3 +-- src/include/deepstate/DeepState.hpp | 6 +++--- src/lib/DeepState.c | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 6838ac4..834d5bb 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -165,8 +165,7 @@ extern void *DeepState_ConcretizeData(void *begin, void *end); /* Assign a symbolic C string of length `len` with only chars in allowed, * if allowed is non-null */ -extern void DeepState_AssignCStr(char* str, size_t len, const char* allowed, - size_t allowed_size); +extern void DeepState_AssignCStr(char* str, size_t len, const char* allowed); /* Return a symbolic C string of length `len`. */ extern char *DeepState_CStr(size_t len); diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index d9f148d..cb27062 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -472,10 +472,10 @@ struct Comparer { }; /* Like DeepState_AssignCStr, but Pumps through possible string sizes. */ -inline static void DeepState_AssignCStrMax(char* str, size_t max_len, const char* allowed, - size_t allowed_size) { +inline static void DeepState_AssignCStrMax(char* str, size_t max_len, + const char* allowed) { uint32_t size = DeepState_UIntInRange(0, max_len); - DeepState_AssignCStr(str, Pump(size, max_len), allowed, allowed_size); + DeepState_AssignCStr(str, Pump(size, max_len), allowed); } /* Like DeepState_CStr, but Pumps through possible string sizes. */ diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 6f2860a..5d81f2b 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -176,14 +176,14 @@ void *DeepState_ConcretizeData(void *begin, void *end) { } /* Assign a symbolic C string of length `len`. */ -void DeepState_AssignCStr(char* str, size_t len, const char* allowed, - size_t allowed_size) { +void DeepState_AssignCStr(char* str, size_t len, const char* allowed) { if (SIZE_MAX == len) { DeepState_Abandon("Can't create an SIZE_MAX-length string."); } if (NULL == str) { DeepState_Abandon("Attempted to populate null pointer."); } + uint32_t allowed_size = strlen(allowed); for (int i = 0; i < len; i++) { str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; } From efb3c07314d8db15510f8f5f2f2321967bc35f64 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 13:06:01 -0700 Subject: [PATCH 05/39] new interface --- src/include/deepstate/DeepState.h | 6 ++--- src/include/deepstate/DeepState.hpp | 29 +++++++++++++++------ src/lib/DeepState.c | 39 +++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 834d5bb..82938fa 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -165,13 +165,13 @@ extern void *DeepState_ConcretizeData(void *begin, void *end); /* Assign a symbolic C string of length `len` with only chars in allowed, * if allowed is non-null */ -extern void DeepState_AssignCStr(char* str, size_t len, const char* allowed); +extern void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed); /* Return a symbolic C string of length `len`. */ -extern char *DeepState_CStr(size_t len); +extern char *DeepState_CStr_C(size_t len, const char* allowed); /* Symbolize a C string */ -void DeepState_SymbolizeCStr(char *begin); +void DeepState_SymbolizeCStr_C(char *begin, const char* allowed); /* Concretize a C string. Returns a pointer to the beginning of the * concretized C string. */ diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index cb27062..17468ce 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -471,17 +471,32 @@ struct Comparer { } }; +/* Like DeepState_AssignCStr_C, but fills in a null allowed. */ +inline static void DeepState_AssignCStr(char* str, size_t len, + const char* allowed = 0) { + DeepState_AssignCStr_C(str, len, allowed); +} + /* Like DeepState_AssignCStr, but Pumps through possible string sizes. */ -inline static void DeepState_AssignCStrMax(char* str, size_t max_len, - const char* allowed) { - uint32_t size = DeepState_UIntInRange(0, max_len); - DeepState_AssignCStr(str, Pump(size, max_len), allowed); +inline static void DeepState_AssignCStrUpToLen(char* str, size_t max_len, + const char* allowed = 0) { + uint32_t len = DeepState_UIntInRange(0, max_len); + DeepState_AssignCStr_C(str, Pump(len, max_len), allowed); } +/* Like DeepState_CStr_C, but fills in a null allowed. */ +inline static char* DeepState_CStr(size_t len, char* allowed = 0) { + return DeepState_CStr_C(len, allowed); +} + /* Like DeepState_CStr, but Pumps through possible string sizes. */ -inline static char* DeepState_CStrMax(size_t max_len) { - uint32_t size = DeepState_UIntInRange(0, max_len); - return DeepState_CStr(Pump(size, max_len)); +inline static char* DeepState_CStrUpToLen(size_t max_len, char* allowed = 0) { + uint32_t len = DeepState_UIntInRange(0, max_len); + return DeepState_CStr_C(Pump(len, max_len), allowed); +} + +inline static void DeepState_SymbolizeCStr_C(char *begin, char* allowed = 0) { + DeepState_SymbolizeCStr_C(begin, allowed); } } // namespace deepstate diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 5d81f2b..036c843 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -176,22 +176,28 @@ void *DeepState_ConcretizeData(void *begin, void *end) { } /* Assign a symbolic C string of length `len`. */ -void DeepState_AssignCStr(char* str, size_t len, const char* allowed) { +void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed) { if (SIZE_MAX == len) { DeepState_Abandon("Can't create an SIZE_MAX-length string."); } if (NULL == str) { DeepState_Abandon("Attempted to populate null pointer."); } - uint32_t allowed_size = strlen(allowed); - for (int i = 0; i < len; i++) { - str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + if (len) { + if (!allowed) { + DeepState_SymbolizeData(str, &(str[len - 1])); + } else { + uint32_t allowed_size = strlen(allowed); + for (int i = 0; i < len; i++) { + str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + } + } } str[len] = '\0'; } /* Return a symbolic C string of length `len`. */ -char *DeepState_CStr(size_t len) { +char *DeepState_CStr_C(size_t len, const char* allowed) { if (SIZE_MAX == len) { DeepState_Abandon("Can't create an SIZE_MAX-length string."); } @@ -201,16 +207,33 @@ char *DeepState_CStr(size_t len) { } DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = str; if (len) { - DeepState_SymbolizeData(str, &(str[len - 1])); + if (!allowed) { + DeepState_SymbolizeData(str, &(str[len - 1])); + } else { + uint32_t allowed_size = strlen(allowed); + for (int i = 0; i < len; i++) { + str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + } + } } str[len] = '\0'; return str; } /* Symbolize a C string */ -void DeepState_SymbolizeCStr(char *begin) { +void DeepState_SymbolizeCStr_C(char *begin, const char* allowed) { if (begin && begin[0]) { - DeepState_SymbolizeData(begin, begin + strlen(begin)); + if (!allowed) { + DeepState_SymbolizeData(begin, begin + strlen(begin)); + } else { + uint32_t allowed_size = strlen(allowed); + uint8_t *bytes = (uint8_t *) begin; + uintptr_t begin_addr = (uintptr_t) begin; + uintptr_t end_addr = (uintptr_t) (begin + strlen(begin)); + for (uintptr_t i = 0, max_i = (end_addr - begin_addr); i < max_i; ++i) { + bytes[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + } + } } } From 943627819ddc4d24c711dd97f2fba21973ba6f8c Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 13:19:57 -0700 Subject: [PATCH 06/39] Fix for new C interface to string generation --- examples/Squares.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Squares.c b/examples/Squares.c index 466ba61..5483512 100644 --- a/examples/Squares.c +++ b/examples/Squares.c @@ -10,7 +10,7 @@ int square(int x) { DeepState_EntryPoint(test_main) { const char *new_args[2]; new_args[0] = "deepstate"; - new_args[1] = DeepState_CStr(8); + new_args[1] = DeepState_CStr_C(8, 0); DeepState_Assert(0 == old_main(2, new_args)); } From 2421a17f5e9b16a5f59f2807119da16492014771 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 13:49:53 -0700 Subject: [PATCH 07/39] add missing const qualifiers --- src/include/deepstate/DeepState.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 17468ce..510cbdc 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -485,17 +485,17 @@ inline static void DeepState_AssignCStrUpToLen(char* str, size_t max_len, } /* Like DeepState_CStr_C, but fills in a null allowed. */ -inline static char* DeepState_CStr(size_t len, char* allowed = 0) { +inline static char* DeepState_CStr(size_t len, const char* allowed = 0) { return DeepState_CStr_C(len, allowed); } /* Like DeepState_CStr, but Pumps through possible string sizes. */ -inline static char* DeepState_CStrUpToLen(size_t max_len, char* allowed = 0) { +inline static char* DeepState_CStrUpToLen(size_t max_len, const char* allowed = 0) { uint32_t len = DeepState_UIntInRange(0, max_len); return DeepState_CStr_C(Pump(len, max_len), allowed); } -inline static void DeepState_SymbolizeCStr_C(char *begin, char* allowed = 0) { +inline static void DeepState_SymbolizeCStr_C(char *begin, const char* allowed = 0) { DeepState_SymbolizeCStr_C(begin, allowed); } From eb1133825a03f4f5fe0943ad002fb9319e082141 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 14:18:01 -0700 Subject: [PATCH 08/39] Add run length example --- examples/CMakeLists.txt | 10 +++++++ examples/Runlen.cpp | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 examples/Runlen.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index f8e7a21..264bc36 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -102,6 +102,16 @@ if (BUILD_LIBFUZZER) set_target_properties(StreamingAndFormatting_LF PROPERTIES COMPILE_DEFINITIONS "LIBFUZZER") endif() +add_executable(Runlen Runlen.cpp) +target_link_libraries(Runlen deepstate) + +if (BUILD_LIBFUZZER) + add_executable(Runlen_LF Runlen.cpp) + target_link_libraries(Runlen_LF deepstate_LF) + target_link_libraries (Runlen_LF "-fsanitize=fuzzer,undefined") + set_target_properties(Runlen_LF PROPERTIES COMPILE_DEFINITIONS "LIBFUZZER") +endif() + if (NOT APPLE) add_executable(Squares Squares.c) target_link_libraries(Squares deepstate) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp new file mode 100644 index 0000000..f0a75e1 --- /dev/null +++ b/examples/Runlen.cpp @@ -0,0 +1,62 @@ +#include + +using namespace deepstate; + +char* encode(const char* input) { + unsigned int l = strlen(input); + char* encoded = (char*)malloc((l*2)+1); + if (l == 0) { + encoded[0] = '\0'; + return encoded; + } + unsigned char last = input[0]; + unsigned char current; + int count = 1; + int pos = 0; + for (int i = 1; i < l; i++) { + current = input[i]; + if ((current == last) && (count < 26)) { + count++; + } else { + encoded[pos++] = last; + encoded[pos++] = 64 + count; + last = current; + count = 1; + } + } + encoded[pos++] = last; + encoded[pos++] = 64 + count; + encoded[pos] = '\0'; + return encoded; +} + +char* decode(const char* output) { + unsigned int l = strlen(output); + char* decoded = (char*)malloc(((l/2)*25)+1); + if (l == 0) { + decoded[0] = '\0'; + return decoded; + } + int pos = 0; + unsigned char current; + for (int i = 0; i < l; i++) { + current = output[i++]; + unsigned int count = output[i] - 64; + for (int j = 0; j < count; j++) { + decoded[pos++] = current; + } + } + decoded[pos] = '\0'; + return decoded; +} + +#define MAX_STR_LEN 100 + +TEST(Runlength, EncodeDecode) { + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcde"); + LOG(TRACE) << "original = `" << original << "`"; + char* encoded = encode(original); + char* roundtrip = decode(encoded); + ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << + "encode = `" << encoded << "`, decode(encode) = `" << roundtrip << "`"; +} From 40eb4b011731ba5d4b80b18e4da34bd9fe27513d Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 14:20:15 -0700 Subject: [PATCH 09/39] add runlen test --- .travis.yml | 2 ++ tests/test_runlen.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/test_runlen.py diff --git a/.travis.yml b/.travis.yml index 2cc49e8..fb8741a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ env: - TASK=ONEOF - TASK=OVERFLOW - TASK=PRIMES +- TASK=RUNLEN - TASK=STREAMINGANDFORMATTING - TASK=TAKEOVER script: @@ -34,6 +35,7 @@ script: - if [ $TASK = KLEE ]; then nosetests tests/test_klee.py ; fi - if [ $TASK = LISTS ]; then nosetests tests/test_lists.py ; fi - if [ $TASK = ONEOF ]; then nosetests tests/test_oneof.py ; fi +- if [ $TASK = RUNLEN ]; then nosetests tests/test_runlen.py ; fi - if [ $TASK = OVERFLOW ]; then nosetests tests/test_overflow.py ; fi - if [ $TASK = PRIMES ]; then nosetests tests/test_primes.py ; fi - if [ $TASK = STREAMINGANDFORMATTING ]; then nosetests tests/test_streamingandformatting.py ; fi diff --git a/tests/test_runlen.py b/tests/test_runlen.py new file mode 100644 index 0000000..a466f13 --- /dev/null +++ b/tests/test_runlen.py @@ -0,0 +1,18 @@ +from __future__ import print_function +import deepstate_base +import logrun + + +class RunlenTest(deepstate_base.DeepStateTestCase): + def run_deepstate(self, deepstate): + (r, output) = logrun.logrun([deepstate, "build/examples/Runlen"], + "deepstate.out", 1800) + self.assertEqual(r, 0) + + self.assertTrue("Passed: Runlength_EncodeDecode" in output) + foundCrashSave = False + for line in output.split("\n"): + if ("Saving input to" in line) and (".crash" in line): + foundCrashSave = True + self.assertTrue(foundCrashSave) + From cd7f6daaf9d3a9c2271b4fcabfe3247db0e9235b Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 14:39:10 -0700 Subject: [PATCH 10/39] change runlen example bug and test --- examples/Runlen.cpp | 8 ++++---- tests/test_runlen.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index f0a75e1..41cda29 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -10,7 +10,7 @@ char* encode(const char* input) { return encoded; } unsigned char last = input[0]; - unsigned char current; + unsigned char current = input[0]; int count = 1; int pos = 0; for (int i = 1; i < l; i++) { @@ -25,14 +25,14 @@ char* encode(const char* input) { } } encoded[pos++] = last; - encoded[pos++] = 64 + count; + encoded[pos++] = 65; encoded[pos] = '\0'; return encoded; } char* decode(const char* output) { unsigned int l = strlen(output); - char* decoded = (char*)malloc(((l/2)*25)+1); + char* decoded = (char*)malloc(((l/2)*26)+1); if (l == 0) { decoded[0] = '\0'; return decoded; @@ -50,7 +50,7 @@ char* decode(const char* output) { return decoded; } -#define MAX_STR_LEN 100 +#define MAX_STR_LEN 10 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcde"); diff --git a/tests/test_runlen.py b/tests/test_runlen.py index a466f13..4e7d8d4 100644 --- a/tests/test_runlen.py +++ b/tests/test_runlen.py @@ -10,9 +10,9 @@ class RunlenTest(deepstate_base.DeepStateTestCase): self.assertEqual(r, 0) self.assertTrue("Passed: Runlength_EncodeDecode" in output) - foundCrashSave = False + foundFailSave = False for line in output.split("\n"): - if ("Saving input to" in line) and (".crash" in line): - foundCrashSave = True - self.assertTrue(foundCrashSave) + if ("Saving input to" in line) and (".fail" in line): + foundFailSave = True + self.assertTrue(foundFailSave) From ec31d0b79948ee5fd13ad0436219c8d7ca2324be Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 15:11:10 -0700 Subject: [PATCH 11/39] change the code and input range --- examples/Runlen.cpp | 51 +++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 41cda29..547090a 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -3,48 +3,31 @@ using namespace deepstate; char* encode(const char* input) { - unsigned int l = strlen(input); - char* encoded = (char*)malloc((l*2)+1); - if (l == 0) { - encoded[0] = '\0'; - return encoded; - } - unsigned char last = input[0]; - unsigned char current = input[0]; - int count = 1; + char* encoded = (char*)malloc((strlen(input)*2)+1); int pos = 0; - for (int i = 1; i < l; i++) { - current = input[i]; - if ((current == last) && (count < 26)) { - count++; - } else { - encoded[pos++] = last; - encoded[pos++] = 64 + count; - last = current; - count = 1; + if (strlen(input) > 0) { + unsigned char last = input[0]; int count = 1; + for (int i = 1; i < strlen(input); i++) { + if (((unsigned char)input[i] == last) && (count < 26)) + count++; + else { + encoded[pos++] = last; encoded[pos++] = 64 + count; + last = (unsigned char)input[i]; count = 1; + } } + encoded[pos++] = last; encoded[pos++] = 65; } - encoded[pos++] = last; - encoded[pos++] = 65; encoded[pos] = '\0'; return encoded; } char* decode(const char* output) { - unsigned int l = strlen(output); - char* decoded = (char*)malloc(((l/2)*26)+1); - if (l == 0) { - decoded[0] = '\0'; - return decoded; - } + char* decoded = (char*)malloc(((strlen(output))/2)*26); int pos = 0; - unsigned char current; - for (int i = 0; i < l; i++) { - current = output[i++]; - unsigned int count = output[i] - 64; - for (int j = 0; j < count; j++) { - decoded[pos++] = current; - } + if (strlen(output) > 0) { + for (int i = 0; i < strlen(output); i += 2) + for (int j = 0; j < (output[i+1] - 64); j++) + decoded[pos++] = output[i]; } decoded[pos] = '\0'; return decoded; @@ -53,7 +36,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 10 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcde"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); LOG(TRACE) << "original = `" << original << "`"; char* encoded = encode(original); char* roundtrip = decode(encoded); From a0ec145b6b33b342874ab63f094742bb39105ce2 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 15:25:43 -0700 Subject: [PATCH 12/39] shrink max string size --- examples/Runlen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 547090a..049fcb4 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -33,7 +33,8 @@ char* decode(const char* output) { return decoded; } -#define MAX_STR_LEN 10 +// Can be higher if we're using fuzzing, not symbolic execution +#define MAX_STR_LEN 7 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From 122f5a7b574571dc10788fae6ada5dc4e5aeedb2 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 15:43:18 -0700 Subject: [PATCH 13/39] smaller limit, concretize --- examples/Runlen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 049fcb4..0c16def 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,10 +34,11 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 7 +#define MAX_STR_LEN 4 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); + DeepState_ConcretizeCStr(original); LOG(TRACE) << "original = `" << original << "`"; char* encoded = encode(original); char* roundtrip = decode(encoded); From 244c3ac3a8a76d3cf1334729f386f0a984af2890 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 15:52:55 -0700 Subject: [PATCH 14/39] Change size, output --- examples/Runlen.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 0c16def..7a22f0a 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,14 +34,12 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 4 +#define MAX_STR_LEN 5 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); - DeepState_ConcretizeCStr(original); - LOG(TRACE) << "original = `" << original << "`"; char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << - "encode = `" << encoded << "`, decode(encode) = `" << roundtrip << "`"; + "`" << original << "` ==> `" << encoded << "` ==> `" << roundtrip << "`"; } From 14863f074499150dc41bb304f04a8416fd6c6490 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 16:40:28 -0700 Subject: [PATCH 15/39] Smaller size for manticore --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 7a22f0a..f9bfc78 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,7 +34,7 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 5 +#define MAX_STR_LEN 4 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From 9c224b4f7b078f9522346031b3ed53d8e8d250ca Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 17:21:19 -0700 Subject: [PATCH 16/39] lower length --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index f9bfc78..836a1e3 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,7 +34,7 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 4 +#define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From 1fb617fe616bc449f4558a62df10e659485a22a9 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 18:09:36 -0700 Subject: [PATCH 17/39] increase Pump len --- src/include/deepstate/DeepState.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 510cbdc..7c6ac8d 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -481,7 +481,7 @@ inline static void DeepState_AssignCStr(char* str, size_t len, inline static void DeepState_AssignCStrUpToLen(char* str, size_t max_len, const char* allowed = 0) { uint32_t len = DeepState_UIntInRange(0, max_len); - DeepState_AssignCStr_C(str, Pump(len, max_len), allowed); + DeepState_AssignCStr_C(str, Pump(len, max_len+1), allowed); } /* Like DeepState_CStr_C, but fills in a null allowed. */ @@ -492,7 +492,7 @@ inline static char* DeepState_CStr(size_t len, const char* allowed = 0) { /* Like DeepState_CStr, but Pumps through possible string sizes. */ inline static char* DeepState_CStrUpToLen(size_t max_len, const char* allowed = 0) { uint32_t len = DeepState_UIntInRange(0, max_len); - return DeepState_CStr_C(Pump(len, max_len), allowed); + return DeepState_CStr_C(Pump(len, max_len+1), allowed); } inline static void DeepState_SymbolizeCStr_C(char *begin, const char* allowed = 0) { From 4d568398715e1dfb5e6ba94432df7e6bb490e27b Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 19:07:45 -0700 Subject: [PATCH 18/39] Shrink for manticore --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 836a1e3..9c4ed68 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,7 +34,7 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 3 +#define MAX_STR_LEN 2 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From ecb0c8e5cc40a5a4135cc7a8d65f9e479563e82a Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 19:09:36 -0700 Subject: [PATCH 19/39] Increase timeout --- tests/test_runlen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_runlen.py b/tests/test_runlen.py index 4e7d8d4..58789f1 100644 --- a/tests/test_runlen.py +++ b/tests/test_runlen.py @@ -6,7 +6,7 @@ import logrun class RunlenTest(deepstate_base.DeepStateTestCase): def run_deepstate(self, deepstate): (r, output) = logrun.logrun([deepstate, "build/examples/Runlen"], - "deepstate.out", 1800) + "deepstate.out", 2700) self.assertEqual(r, 0) self.assertTrue("Passed: Runlength_EncodeDecode" in output) From c3136f77fd01ec12750f6bb4836b6429b2368e01 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 19:10:09 -0700 Subject: [PATCH 20/39] Back to length 3 --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 9c4ed68..836a1e3 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,7 +34,7 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 2 +#define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From d410c0df5ff8b9ab5c48812da0f245bb94c193f8 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 20:00:54 -0700 Subject: [PATCH 21/39] back to 2 for manticore --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 836a1e3..9c4ed68 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -34,7 +34,7 @@ char* decode(const char* output) { } // Can be higher if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 3 +#define MAX_STR_LEN 2 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); From da18a1ae0b3f7540423aabca4ddc6c3efaf36c17 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 22:59:41 -0700 Subject: [PATCH 22/39] more comments --- examples/Runlen.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 9c4ed68..7d92daa 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -2,6 +2,9 @@ using namespace deepstate; +/* Simple, buggy, run-length encoding that creates "human readable" + * encodings by adding 'A'-1 to the count, and splitting at 26 */ + char* encode(const char* input) { char* encoded = (char*)malloc((strlen(input)*2)+1); int pos = 0; @@ -15,7 +18,7 @@ char* encode(const char* input) { last = (unsigned char)input[i]; count = 1; } } - encoded[pos++] = last; encoded[pos++] = 65; + encoded[pos++] = last; encoded[pos++] = 65; // Should be count, not 65! } encoded[pos] = '\0'; return encoded; @@ -33,7 +36,7 @@ char* decode(const char* output) { return decoded; } -// Can be higher if we're using fuzzing, not symbolic execution +// Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution #define MAX_STR_LEN 2 TEST(Runlength, EncodeDecode) { From 00b77202e397f0eb7c2dc6c3c50bdb18f10a359b Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Mon, 31 Dec 2018 23:13:58 -0700 Subject: [PATCH 23/39] fix comment on bug --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 7d92daa..42b86ee 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -18,7 +18,7 @@ char* encode(const char* input) { last = (unsigned char)input[i]; count = 1; } } - encoded[pos++] = last; encoded[pos++] = 65; // Should be count, not 65! + encoded[pos++] = last; encoded[pos++] = 65; // Should be 64 + count } encoded[pos] = '\0'; return encoded; From 7431a9bd1bdf0c8299672750e40e05c877eb102c Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 01:20:09 -0700 Subject: [PATCH 24/39] fix OBOB, increase length since this may be what slowed manticore down --- examples/Runlen.cpp | 2 +- src/lib/DeepState.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 42b86ee..235930a 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -37,7 +37,7 @@ char* decode(const char* output) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 2 +#define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 036c843..9e17175 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -189,7 +189,7 @@ void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed) { } else { uint32_t allowed_size = strlen(allowed); for (int i = 0; i < len; i++) { - str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + str[i] = allowed[DeepState_UIntInRange(0, allowed_size-1)]; } } } @@ -212,7 +212,7 @@ char *DeepState_CStr_C(size_t len, const char* allowed) { } else { uint32_t allowed_size = strlen(allowed); for (int i = 0; i < len; i++) { - str[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + str[i] = allowed[DeepState_UIntInRange(0, allowed_size-1)]; } } } @@ -231,7 +231,7 @@ void DeepState_SymbolizeCStr_C(char *begin, const char* allowed) { uintptr_t begin_addr = (uintptr_t) begin; uintptr_t end_addr = (uintptr_t) (begin + strlen(begin)); for (uintptr_t i = 0, max_i = (end_addr - begin_addr); i < max_i; ++i) { - bytes[i] = allowed[DeepState_UIntInRange(0, allowed_size)]; + bytes[i] = allowed[DeepState_UIntInRange(0, allowed_size-1)]; } } } From e3bba13fd2f7458cbef5f7f239cb16b2e61a819d Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 08:01:32 -0700 Subject: [PATCH 25/39] Increase timeout for manticore --- tests/test_runlen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_runlen.py b/tests/test_runlen.py index 58789f1..545129a 100644 --- a/tests/test_runlen.py +++ b/tests/test_runlen.py @@ -6,7 +6,7 @@ import logrun class RunlenTest(deepstate_base.DeepStateTestCase): def run_deepstate(self, deepstate): (r, output) = logrun.logrun([deepstate, "build/examples/Runlen"], - "deepstate.out", 2700) + "deepstate.out", 2900) self.assertEqual(r, 0) self.assertTrue("Passed: Runlength_EncodeDecode" in output) From bfa85a09c3009ab7769ba2ee0bbedc1fd68d2bb5 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 12:04:06 -0700 Subject: [PATCH 26/39] bigger alphabet --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 235930a..fe86d0e 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -40,7 +40,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "ab"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcdefghijklmnopqrstuvwxyz0123456789"); char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << From 46f0eeb4b4ce3c17ba88deb1834ea38bd71c0fa2 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 12:36:31 -0700 Subject: [PATCH 27/39] hex alphabet --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index fe86d0e..c979c05 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -40,7 +40,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcdefghijklmnopqrstuvwxyz0123456789"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcdef0123456789"); char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << From c67b0329b6e39f253c4e935db49b552e4a0f46b5 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 12:54:59 -0700 Subject: [PATCH 28/39] numeric alphabet --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index c979c05..24546c0 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -40,7 +40,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abcdef0123456789"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "0123456789"); char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << From 71fbb7ac7df58b5ddcc768bf4a20d5ab5c4b8a8c Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 13:03:01 -0700 Subject: [PATCH 29/39] 3 char alphabet --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 24546c0..0d402a7 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -40,7 +40,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "0123456789"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abc"); char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << From 303159467e4b672c4cdf8a3c0b58b4a901f0b052 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 13:58:59 -0700 Subject: [PATCH 30/39] no alphabet at all --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 0d402a7..3b431ee 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -40,7 +40,7 @@ char* decode(const char* output) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN, "abc"); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN); char* encoded = encode(original); char* roundtrip = decode(encoded); ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << From 9ef6c5ea32e3f740c001486a3c34478d1ebb9983 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 14:38:48 -0700 Subject: [PATCH 31/39] different printout --- examples/Runlen.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 3b431ee..70267b4 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -6,11 +6,12 @@ using namespace deepstate; * encodings by adding 'A'-1 to the count, and splitting at 26 */ char* encode(const char* input) { - char* encoded = (char*)malloc((strlen(input)*2)+1); + unsigned int len = strlen(input); + char* encoded = (char*)malloc((len*2)+1); int pos = 0; if (strlen(input) > 0) { unsigned char last = input[0]; int count = 1; - for (int i = 1; i < strlen(input); i++) { + for (int i = 1; i < len; i++) { if (((unsigned char)input[i] == last) && (count < 26)) count++; else { @@ -25,10 +26,11 @@ char* encode(const char* input) { } char* decode(const char* output) { - char* decoded = (char*)malloc(((strlen(output))/2)*26); + unsigned int len = strlen(output); + char* decoded = (char*)malloc((len/2)*26); int pos = 0; if (strlen(output) > 0) { - for (int i = 0; i < strlen(output); i += 2) + for (int i = 0; i < len; i += 2) for (int j = 0; j < (output[i+1] - 64); j++) decoded[pos++] = output[i]; } @@ -36,6 +38,12 @@ char* decode(const char* output) { return decoded; } +void printBytes(const char* bytes) { + unsigned int len = strlen(bytes); + for (int i = 0; i < len; i++) + LOG(ERROR) << "[" << i << "] = " << (unsigned int)(unsigned char)bytes[i]; +} + // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution #define MAX_STR_LEN 3 @@ -43,6 +51,13 @@ TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); char* encoded = encode(original); char* roundtrip = decode(encoded); - ASSERT (strncmp(roundtrip, original, MAX_STR_LEN) == 0) << - "`" << original << "` ==> `" << encoded << "` ==> `" << roundtrip << "`"; + if (!(strncmp(roundtrip, original, MAX_STR_LEN) == 0)) { + LOG(ERROR) << "ORIGINAL:"; + printBytes(original); + LOG(ERROR) << "ENCODED:"; + printBytes(encoded); + LOG(ERROR) << "ROUNDTRIP:"; + printBytes(roundtrip); + ASSERT (0) << "Round trip check failed"; + } } From 31460e7f0d81e5e0e59972da4008464c89cce9b9 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 16:58:31 -0700 Subject: [PATCH 32/39] Don't Pump through sizes, since the functions allow null terminators anyway --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 70267b4..dcfe123 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -48,7 +48,7 @@ void printBytes(const char* bytes) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStrUpToLen(MAX_STR_LEN); + char* original = DeepState_CStr(MAX_STR_LEN); char* encoded = encode(original); char* roundtrip = decode(encoded); if (!(strncmp(roundtrip, original, MAX_STR_LEN) == 0)) { From cc2925ffd2cfd001d4faa5196f5a288ab59c7374 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 18:59:25 -0700 Subject: [PATCH 33/39] fix off by one in call to symbolize, and avoid nulls --- examples/Runlen.cpp | 2 +- src/include/deepstate/DeepState.h | 3 +++ src/lib/DeepState.c | 32 ++++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index dcfe123..70267b4 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -48,7 +48,7 @@ void printBytes(const char* bytes) { #define MAX_STR_LEN 3 TEST(Runlength, EncodeDecode) { - char* original = DeepState_CStr(MAX_STR_LEN); + char* original = DeepState_CStrUpToLen(MAX_STR_LEN); char* encoded = encode(original); char* roundtrip = decode(encoded); if (!(strncmp(roundtrip, original, MAX_STR_LEN) == 0)) { diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 82938fa..b6c102c 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -159,6 +159,9 @@ extern int DeepState_ZeroSink(int); /* Symbolize the data in the exclusive range `[begin, end)`. */ extern void DeepState_SymbolizeData(void *begin, void *end); +/* Symbolize the data in the exclusive range `[begin, end)` with no nulls. */ +extern void DeepState_SymbolizeDataNoNull(void *begin, void *end); + /* Concretize some data in exclusive the range `[begin, end)`. Returns a * concrete pointer to the beginning of the concretized data. */ extern void *DeepState_ConcretizeData(void *begin, void *end); diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 9e17175..38d743a 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -170,6 +170,32 @@ void DeepState_SymbolizeData(void *begin, void *end) { } } +/* Symbolize the data in the exclusive range `[begin, end)`. */ +void DeepState_SymbolizeDataNoNull(void *begin, void *end) { + uintptr_t begin_addr = (uintptr_t) begin; + uintptr_t end_addr = (uintptr_t) end; + + if (begin_addr > end_addr) { + DeepState_Abandon("Invalid data bounds for DeepState_SymbolizeData"); + } else if (begin_addr == end_addr) { + return; + } else { + uint8_t *bytes = (uint8_t *) begin; + for (uintptr_t i = 0, max_i = (end_addr - begin_addr); i < max_i; ++i) { + if (DeepState_InputIndex >= DeepState_InputSize) { + DeepState_Abandon("Read too many symbols"); + } + if (FLAGS_verbose_reads) { + printf("Reading byte at %u\n", DeepState_InputIndex); + } + bytes[i] = DeepState_Input[DeepState_InputIndex++]; + if (bytes[i] == 0) { + bytes[i] = 1; + } + } + } +} + /* Concretize some data in exclusive the range `[begin, end)`. */ void *DeepState_ConcretizeData(void *begin, void *end) { return begin; @@ -185,7 +211,7 @@ void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed) { } if (len) { if (!allowed) { - DeepState_SymbolizeData(str, &(str[len - 1])); + DeepState_SymbolizeDataNoNull(str, &(str[len])); } else { uint32_t allowed_size = strlen(allowed); for (int i = 0; i < len; i++) { @@ -208,7 +234,7 @@ char *DeepState_CStr_C(size_t len, const char* allowed) { DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = str; if (len) { if (!allowed) { - DeepState_SymbolizeData(str, &(str[len - 1])); + DeepState_SymbolizeDataNoNull(str, &(str[len])); } else { uint32_t allowed_size = strlen(allowed); for (int i = 0; i < len; i++) { @@ -224,7 +250,7 @@ char *DeepState_CStr_C(size_t len, const char* allowed) { void DeepState_SymbolizeCStr_C(char *begin, const char* allowed) { if (begin && begin[0]) { if (!allowed) { - DeepState_SymbolizeData(begin, begin + strlen(begin)); + DeepState_SymbolizeDataNoNull(begin, begin + strlen(begin)); } else { uint32_t allowed_size = strlen(allowed); uint8_t *bytes = (uint8_t *) begin; From a6db7fb09700c5677b0a2ed8b58247a79170f655 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 19:52:48 -0700 Subject: [PATCH 34/39] drop manticore for runlen, longer limit --- examples/Runlen.cpp | 2 +- tests/test_runlen.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 70267b4..e3957f5 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -45,7 +45,7 @@ void printBytes(const char* bytes) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 3 +#define MAX_STR_LEN 4 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); diff --git a/tests/test_runlen.py b/tests/test_runlen.py index 545129a..a378329 100644 --- a/tests/test_runlen.py +++ b/tests/test_runlen.py @@ -5,6 +5,8 @@ import logrun class RunlenTest(deepstate_base.DeepStateTestCase): def run_deepstate(self, deepstate): + if deepstate == "deepstate-manticore": + return # Just skip for now, we know it's too slow (r, output) = logrun.logrun([deepstate, "build/examples/Runlen"], "deepstate.out", 2900) self.assertEqual(r, 0) From 483e827c64f7e40ae7fa23693ca816152114659f Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 21:31:47 -0700 Subject: [PATCH 35/39] up to 6 since only angr --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index e3957f5..b7d12aa 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -45,7 +45,7 @@ void printBytes(const char* bytes) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 4 +#define MAX_STR_LEN 6 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); From 6cbb4f479ab09d150dc6b1497085336f05fa518c Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Tue, 1 Jan 2019 22:43:57 -0700 Subject: [PATCH 36/39] note it's STRLEN not length including null, expand Runlen size --- examples/Runlen.cpp | 2 +- src/include/deepstate/DeepState.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index b7d12aa..5f9144b 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -45,7 +45,7 @@ void printBytes(const char* bytes) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 6 +#define MAX_STR_LEN 8 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index b6c102c..5d29160 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -166,11 +166,11 @@ extern void DeepState_SymbolizeDataNoNull(void *begin, void *end); * concrete pointer to the beginning of the concretized data. */ extern void *DeepState_ConcretizeData(void *begin, void *end); -/* Assign a symbolic C string of length `len` with only chars in allowed, - * if allowed is non-null */ +/* Assign a symbolic C string of _strlen_ `len` -- with only chars in allowed, + * if allowed is non-null; needs space for null + len bytes */ extern void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed); -/* Return a symbolic C string of length `len`. */ +/* Return a symbolic C string of strlen `len`. */ extern char *DeepState_CStr_C(size_t len, const char* allowed); /* Symbolize a C string */ From d40c48efa590367947c4f9d84311ae8e825179b0 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Wed, 2 Jan 2019 00:27:52 -0700 Subject: [PATCH 37/39] Shrink size --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 5f9144b..60f3fcb 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -45,7 +45,7 @@ void printBytes(const char* bytes) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 8 +#define MAX_STR_LEN 7 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); From 87fcbf3481d36d8d8339b54211418b7668b0714f Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Wed, 2 Jan 2019 01:09:13 -0700 Subject: [PATCH 38/39] back to 6 --- examples/Runlen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Runlen.cpp b/examples/Runlen.cpp index 60f3fcb..b7d12aa 100644 --- a/examples/Runlen.cpp +++ b/examples/Runlen.cpp @@ -45,7 +45,7 @@ void printBytes(const char* bytes) { } // Can be (much) higher (e.g., > 1024) if we're using fuzzing, not symbolic execution -#define MAX_STR_LEN 7 +#define MAX_STR_LEN 6 TEST(Runlength, EncodeDecode) { char* original = DeepState_CStrUpToLen(MAX_STR_LEN); From 240eb9f813de925770f7787ea5975bc6ce665d31 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Wed, 2 Jan 2019 13:53:15 -0700 Subject: [PATCH 39/39] improve comments --- src/include/deepstate/DeepState.h | 2 +- src/include/deepstate/DeepState.hpp | 7 ++++--- src/lib/DeepState.c | 11 +++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index 5d29160..8827276 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -167,7 +167,7 @@ extern void DeepState_SymbolizeDataNoNull(void *begin, void *end); extern void *DeepState_ConcretizeData(void *begin, void *end); /* Assign a symbolic C string of _strlen_ `len` -- with only chars in allowed, - * if allowed is non-null; needs space for null + len bytes */ + * if `allowed` is non-null; needs space for null + len bytes */ extern void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed); /* Return a symbolic C string of strlen `len`. */ diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 7c6ac8d..00bb1d9 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -471,7 +471,7 @@ struct Comparer { } }; -/* Like DeepState_AssignCStr_C, but fills in a null allowed. */ +/* Like DeepState_AssignCStr_C, but fills in a null `allowed` value. */ inline static void DeepState_AssignCStr(char* str, size_t len, const char* allowed = 0) { DeepState_AssignCStr_C(str, len, allowed); @@ -484,7 +484,7 @@ inline static void DeepState_AssignCStrUpToLen(char* str, size_t max_len, DeepState_AssignCStr_C(str, Pump(len, max_len+1), allowed); } -/* Like DeepState_CStr_C, but fills in a null allowed. */ +/* Like DeepState_CStr_C, but fills in a null `allowed` value. */ inline static char* DeepState_CStr(size_t len, const char* allowed = 0) { return DeepState_CStr_C(len, allowed); } @@ -495,7 +495,8 @@ inline static char* DeepState_CStrUpToLen(size_t max_len, const char* allowed = return DeepState_CStr_C(Pump(len, max_len+1), allowed); } -inline static void DeepState_SymbolizeCStr_C(char *begin, const char* allowed = 0) { +/* Like DeepState_Symbolize_CStr, but fills in null `allowed` value. */ +inline static void DeepState_SymbolizeCStr(char *begin, const char* allowed = 0) { DeepState_SymbolizeCStr_C(begin, allowed); } diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 38d743a..794a3c9 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -170,7 +170,8 @@ void DeepState_SymbolizeData(void *begin, void *end) { } } -/* Symbolize the data in the exclusive range `[begin, end)`. */ +/* Symbolize the data in the exclusive range `[begin, end)` without null + * characters included. Primarily useful for C strings. */ void DeepState_SymbolizeDataNoNull(void *begin, void *end) { uintptr_t begin_addr = (uintptr_t) begin; uintptr_t end_addr = (uintptr_t) end; @@ -201,7 +202,9 @@ void *DeepState_ConcretizeData(void *begin, void *end) { return begin; } -/* Assign a symbolic C string of length `len`. */ +/* Assign a symbolic C string of strlen length `len`. str should include + * storage for both `len` characters AND the null terminator. Allowed + * is a set of chars that are allowed (ignored if null). */ void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed) { if (SIZE_MAX == len) { DeepState_Abandon("Can't create an SIZE_MAX-length string."); @@ -222,7 +225,7 @@ void DeepState_AssignCStr_C(char* str, size_t len, const char* allowed) { str[len] = '\0'; } -/* Return a symbolic C string of length `len`. */ +/* Return a symbolic C string of strlen `len`. */ char *DeepState_CStr_C(size_t len, const char* allowed) { if (SIZE_MAX == len) { DeepState_Abandon("Can't create an SIZE_MAX-length string."); @@ -246,7 +249,7 @@ char *DeepState_CStr_C(size_t len, const char* allowed) { return str; } -/* Symbolize a C string */ +/* Symbolize a C string; keeps the null terminator where it was. */ void DeepState_SymbolizeCStr_C(char *begin, const char* allowed) { if (begin && begin[0]) { if (!allowed) {