post_process 0/NULL return support
MODIFY
docs/Changelog.md
docs/Changelog.md
@@ -9,6 +9,9 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++4.02a (dev)
+ - afl-fuzz:
+ - change post_process hook to allow returning NULL and 0 length to
+ tell afl-fuzz to skip this mutated input
- gcc_plugin:
- Adacore submitted CMPLOG support to the gcc_plugin! :-)
- llvm_mode:

MODIFY
docs/custom_mutators.md
docs/custom_mutators.md
@@ -159,6 +159,10 @@ def deinit(): # optional for Python
This can return any python object that implements the buffer protocol and
supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
+ You can decide in the post_process mutator to not send the mutated data
+ to the target, e.g. if it is too short, too corrupted, etc. If so,
+ return a NULL buffer and zero length (or a 0 length string in Python).
+
- `queue_new_entry` (optional):
This methods is called after adding a new test case to the queue. If the

MODIFY
src/afl-fuzz-bitmap.c
src/afl-fuzz-bitmap.c
@@ -648,7 +648,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (afl->fsrv.exec_tmout < afl->hang_tmout) {
u8 new_fault;
- len = write_to_testcase(afl, &mem, len, 0);
+ u32 tmp_len = write_to_testcase(afl, &mem, len, 0);
+
+ if (likely(tmp_len)) {
+
+ len = tmp_len;
+
+ } else {
+
+ len = write_to_testcase(afl, &mem, len, 1);
+
+ }
+
new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
classify_counts(&afl->fsrv);

MODIFY
src/afl-fuzz-cmplog.c
src/afl-fuzz-cmplog.c
@@ -48,8 +48,17 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
+ u32 tmp_len = write_to_testcase(afl, (void **)&out_buf, len, 0);
- write_to_testcase(afl, (void **)&out_buf, len, 0);
+ if (likely(tmp_len)) {
+
+ len = tmp_len;
+
+ } else {
+
+ len = write_to_testcase(afl, (void **)&out_buf, len, 1);
+
+ }
fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);

MODIFY
src/afl-fuzz-mutators.c
src/afl-fuzz-mutators.c
@@ -430,6 +430,12 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
retlen = write_to_testcase(afl, (void **)&retbuf, retlen, 0);
+ if (unlikely(!retlen)) {
+
+ ++afl->trim_execs;
+
+ } else {
+
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs;
@@ -440,6 +446,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
}
+ }
+
if (likely(retlen && cksum == q->exec_cksum)) {
/* Let's save a clean trace, which will be needed by

MODIFY
src/afl-fuzz-python.c
src/afl-fuzz-python.c
@@ -535,7 +535,16 @@ size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
Py_DECREF(py_value);
+ if (unlikely(py->post_process_buf.len == 0)) {
+
+ *out_buf = NULL;
+
+ } else {
+
*out_buf = (u8 *)py->post_process_buf.buf;
+
+ }
+
return py->post_process_buf.len;
} else {

MODIFY
src/afl-fuzz-run.c
src/afl-fuzz-run.c
@@ -109,17 +109,36 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
if (unlikely(!new_buf && new_size <= 0)) {
- FATAL("Custom_post_process failed (ret: %lu)",
- (long unsigned)new_size);
+ new_size = 0;
+ new_buf = new_mem;
+ // FATAL("Custom_post_process failed (ret: %lu)", (long
+ // unsigned)new_size);
- }
+ } else {
new_mem = new_buf;
}
+ }
+
});
+ if (unlikely(!new_size)) {
+
+ // perform dummy runs (fix = 1), but skip all others
+ if (fix) {
+
+ new_size = len;
+
+ } else {
+
+ return 0;
+
+ }
+
+ }
+
if (unlikely(new_size < afl->min_length && !fix)) {
new_size = afl->min_length;
@@ -969,7 +988,11 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
- len = write_to_testcase(afl, (void **)&out_buf, len, 0);
+ if (unlikely(len = write_to_testcase(afl, (void **)&out_buf, len, 0) == 0)) {
+
+ return 0;
+
+ }
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);

post_process 0/NULL return support