Skip to content

Commit

Permalink
Merge pull request trailofbits#346 from trailofbits/gc_malloc
Browse files Browse the repository at this point in the history
Provides a garbage collecting DeepState malloc
  • Loading branch information
agroce authored Mar 12, 2020
2 parents 4856d50 + 96a940c commit a22ff7e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
13 changes: 12 additions & 1 deletion docs/test_harness.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,20 @@ and the position of a null terminator, are chosen by the
fuzzer/symbolic execution tool.

`void *DeepState_Malloc(size_t num_bytes)` just
allocate `num_bytes` symbolic bytes, of any value. **Failing to free
allocates `num_bytes` symbolic bytes, with arbitrary value. **Failing to free
this pointer will lead to a memory leak, it's just a normal pointer.**

`void *DeepState_GCMalloc(size_t num_bytes)` also
allocates `num_bytes` symbolic bytes, with arbitrary value, but
DeepState will free the pointer after the test is finished, even if
the test exits abnormally. **Freeing THIS pointer will lead to a
double-free error.**

If you can be sure nothing you pass it to frees DeepState-allocated
memory, `DeepState_GCMalloc` is probably your best bet; it will work
much more nicely with libFuzzer and the `no_fork` option, where memory
leaks in tests are a big problem.

#### ForAll
`ForAll`
creates temporary variables which may be used in lambda expressions.
Expand Down
4 changes: 4 additions & 0 deletions src/include/deepstate/DeepState.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ extern const char *DeepState_ConcretizeCStr(const char *begin);
/* Allocate and return a pointer to `num_bytes` symbolic bytes. */
extern void *DeepState_Malloc(size_t num_bytes);

/* Allocate and return a pointer to `num_bytes` symbolic bytes.
Ptr will be freed by DeepState at end of test. */
extern void *DeepState_GCMalloc(size_t num_bytes);

/* Returns the path to a testcase without parsing to any aforementioned types */
extern const char *DeepState_InputPath(char *testcase_path);

Expand Down
25 changes: 17 additions & 8 deletions src/lib/DeepState.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ int DeepState_UsingLibFuzzer = 0;
/* To make libFuzzer louder on mac OS. */
int DeepState_LibFuzzerLoud = 0;

/* Array of DeepState generated strings. Impossible for there to
/* Array of DeepState generated allocations. 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;
char* DeepState_GeneratedAllocs[DeepState_InputSize];
uint32_t DeepState_GeneratedAllocsIndex = 0;

/* Pointer to the last registers DeepState_TestInfo data structure */
struct DeepState_TestInfo *DeepState_LastTestInfo = NULL;
Expand Down Expand Up @@ -282,7 +282,7 @@ char *DeepState_CStr_C(size_t len, const char* allowed) {
if (NULL == str) {
DeepState_Abandon("Can't allocate memory");
}
DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = str;
DeepState_GeneratedAllocs[DeepState_GeneratedAllocsIndex++] = str;
if (len) {
if (allowed == 0) {
DeepState_SymbolizeDataNoNull(str, &(str[len]));
Expand Down Expand Up @@ -315,7 +315,7 @@ char *DeepState_SwarmCStr_C(const char* file, unsigned line, int stype,
swarm_allowed[255] = 0;
allowed = (const char*)&swarm_allowed;
}
DeepState_GeneratedStrings[DeepState_GeneratedStringsIndex++] = str;
DeepState_GeneratedAllocs[DeepState_GeneratedAllocsIndex++] = str;
if (len) {
uint32_t allowed_size = strlen(allowed);
struct DeepState_SwarmConfig* sc = DeepState_GetSwarmConfig(allowed_size, file, line, stype);
Expand Down Expand Up @@ -380,6 +380,15 @@ void *DeepState_Malloc(size_t num_bytes) {
return data;
}

/* Allocate and return a pointer to `num_bytes` symbolic bytes. */
void *DeepState_GCMalloc(size_t num_bytes) {
void *data = malloc(num_bytes);
uintptr_t data_end = ((uintptr_t) data) + num_bytes;
DeepState_SymbolizeData(data, (void *) data_end);
DeepState_GeneratedAllocs[DeepState_GeneratedAllocsIndex++] = data;
return data;
}

/* Portable and architecture-independent memory scrub without dead store elimination. */
void *DeepState_MemScrub(void *pointer, size_t data_size) {
volatile unsigned char *p = pointer;
Expand Down Expand Up @@ -664,10 +673,10 @@ int32_t DeepState_MaxInt(int32_t v) {

/* 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]);
for (int i = 0; i < DeepState_GeneratedAllocsIndex; i++) {
free(DeepState_GeneratedAllocs[i]);
}
DeepState_GeneratedStringsIndex = 0;
DeepState_GeneratedAllocsIndex = 0;

for (int i = 0; i < DeepState_SwarmConfigsIndex; i++) {
free(DeepState_SwarmConfigs[i]->file);
Expand Down

0 comments on commit a22ff7e

Please sign in to comment.