aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-fuzz-mutators.c21
-rw-r--r--src/afl-fuzz-python.c55
-rw-r--r--src/afl-fuzz-run.c52
3 files changed, 112 insertions, 16 deletions
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 0b0c3394..fac97f8e 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -80,6 +80,14 @@ void destroy_custom_mutator(afl_state_t *afl) {
if (afl->mutator->dh) dlclose(afl->mutator->dh);
+ if (afl->mutator->pre_save_buf) {
+
+ ck_free(afl->mutator->pre_save_buf);
+ afl->mutator->pre_save_buf = NULL;
+ afl->mutator->pre_save_size = 0;
+
+ }
+
ck_free(afl->mutator);
afl->mutator = NULL;
@@ -91,6 +99,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
void *dh;
afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+ afl->mutator->pre_save_buf = NULL;
+ afl->mutator->pre_save_size = 0;
afl->mutator->name = fn;
ACTF("Loading custom mutator library from '%s'...", fn);
@@ -125,9 +135,18 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
/* "afl_custom_pre_save", optional */
afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
- if (!afl->mutator->afl_custom_pre_save)
+ if (!afl->mutator->afl_custom_pre_save) {
+
WARNF("Symbol 'afl_custom_pre_save' not found.");
+ } else {
+
+ /* if we have a pre_save hook, prealloc some memory. */
+ afl->mutator->pre_save_buf = ck_alloc(PRE_SAVE_BUF_INIT_SIZE * sizeof(u8));
+ afl->mutator->pre_save_size = PRE_SAVE_BUF_INIT_SIZE;
+
+ }
+
u8 notrim = 0;
/* "afl_custom_init_trim", optional */
afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 418497d0..b053e8d5 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -287,6 +287,8 @@ void deinit_py(void *py_mutator) {
void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
afl->mutator = ck_alloc(sizeof(struct custom_mutator));
+ afl->mutator->pre_save_buf = NULL;
+ afl->mutator->pre_save_size = 0;
afl->mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
@@ -305,8 +307,14 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
is quite different from the custom mutator. */
afl->mutator->afl_custom_fuzz = fuzz_py;
- if (py_functions[PY_FUNC_PRE_SAVE])
+ if (py_functions[PY_FUNC_PRE_SAVE]) {
+
afl->mutator->afl_custom_pre_save = pre_save_py;
+ /* if we have a pre_save hook, prealloc some memory. */
+ afl->mutator->pre_save_buf = ck_alloc(PRE_SAVE_BUF_INIT_SIZE * sizeof(u8));
+ afl->mutator->pre_save_size = PRE_SAVE_BUF_INIT_SIZE;
+
+ }
if (py_functions[PY_FUNC_INIT_TRIM])
afl->mutator->afl_custom_init_trim = init_trim_py;
@@ -336,10 +344,33 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
}
-size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
+size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 *out_buf,
+ size_t out_buf_size) {
- size_t out_buf_size;
+ size_t py_out_buf_size;
PyObject *py_args, *py_value;
+
+ if (((py_mutator_t *)py_mutator)->scratch_buf) {
+
+ /* We are being recalled from an earlier run
+ where we didn't have enough mem. */
+ if (((py_mutator_t *)py_mutator)->scratch_size < out_buf_size) {
+
+ FATAL("out_buf is still too small after resizing in custom mutator.");
+
+ }
+
+ py_value = ((py_mutator_t *)py_mutator)->scratch_buf;
+ py_out_buf_size = ((py_mutator_t *)py_mutator)->scratch_size;
+ ((py_mutator_t *)py_mutator)->scratch_buf = NULL;
+ py_out_buf_size = 0;
+
+ memcpy(out_buf, PyByteArray_AsString(py_value), py_out_buf_size);
+ Py_DECREF(py_value);
+ return py_out_buf_size;
+
+ }
+
py_args = PyTuple_New(1);
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
if (!py_value) {
@@ -358,11 +389,21 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
if (py_value != NULL) {
- out_buf_size = PyByteArray_Size(py_value);
- *out_buf = malloc(out_buf_size);
- memcpy(*out_buf, PyByteArray_AsString(py_value), out_buf_size);
+ py_out_buf_size = PyByteArray_Size(py_value);
+ if (py_out_buf_size > out_buf_size) {
+
+ /* Not enough space!
+ We will get called again right after resizing the buf.
+ Keep the references to our data for now. */
+ ((py_mutator_t *)py_mutator)->scratch_buf = py_value;
+ ((py_mutator_t *)py_mutator)->scratch_size = py_out_buf_size;
+ return py_out_buf_size;
+
+ }
+
+ memcpy(out_buf, PyByteArray_AsString(py_value), py_out_buf_size);
Py_DECREF(py_value);
- return out_buf_size;
+ return py_out_buf_size;
} else {
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index e8ef3049..a539b469 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -216,14 +216,49 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
if (afl->mutator && afl->mutator->afl_custom_pre_save) {
- u8 * new_data;
- size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
- len, &new_data);
- ck_write(fd, new_data, new_size, afl->fsrv.out_file);
- free(new_data);
+ if (unlikely(afl->mutator->pre_save_size < len)) {
+
+ afl->mutator->pre_save_buf =
+ ck_realloc(afl->mutator->pre_save_buf, len * sizeof(u8));
+ afl->mutator->pre_save_size = len;
+
+ }
+
+ u8 buf_written = 0;
+ while (!buf_written) {
+
+ buf_written = 1;
+ size_t new_size = afl->mutator->afl_custom_pre_save(
+ afl->mutator->data, mem, len, afl->mutator->pre_save_buf,
+ afl->mutator->pre_save_size);
+
+ if (unlikely(new_size) == 0) {
+
+ /* custom_pre_save wants us to use the old buf */
+ ck_write(fd, mem, len, afl->fsrv.out_file);
+
+ } else if (unlikely(new_size) > afl->mutator->pre_save_size) {
+
+ /* The custom func needs more space.
+ Realloc and call again. */
+ afl->mutator->pre_save_buf =
+ ck_realloc(afl->mutator->pre_save_buf, new_size * sizeof(u8));
+ afl->mutator->pre_save_size = new_size;
+ buf_written = 0;
+ continue;
+
+ } else {
+
+ /* everything as planned. use the new data. */
+ ck_write(fd, afl->mutator->pre_save_buf, new_size, afl->fsrv.out_file);
+
+ }
+
+ }
} else {
+ /* boring uncustom. */
ck_write(fd, mem, len, afl->fsrv.out_file);
}
@@ -505,8 +540,8 @@ void sync_fuzzers(afl_state_t *afl) {
afl->stage_cur = 0;
afl->stage_max = 0;
- /* For every file queued by this fuzzer, parse ID and see if we have looked
- at it before; exec a test case if not. */
+ /* For every file queued by this fuzzer, parse ID and see if we have
+ looked at it before; exec a test case if not. */
while ((qd_ent = readdir(qd))) {
@@ -645,7 +680,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
- /* Note that we don't keep track of crashes or hangs here; maybe TODO? */
+ /* Note that we don't keep track of crashes or hangs here; maybe TODO?
+ */
cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);