From 7f3e04cbc4d1ea54f743bce1fe7fe31d2fc4de8e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 24 Mar 2020 08:44:18 +0100 Subject: [PATCH 01/97] fix doc link --- examples/custom_mutators/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md index 93f824cd..e5af5516 100644 --- a/examples/custom_mutators/README.md +++ b/examples/custom_mutators/README.md @@ -1,7 +1,7 @@ # Examples for the custom mutator These are example and helper files for the custom mutator feature. -See [docs/python_mutators.md](../docs/custom_mutators.md) for more information +See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information Note that if you compile with python3.7 you must use python3 scripts, and if you use pyton2.7 to compile python2 scripts! From ce58790fc0b7a69edf54ad9becbbf4cc27499033 Mon Sep 17 00:00:00 2001 From: fuzzah <60884276+fuzzah@users.noreply.github.com> Date: Tue, 24 Mar 2020 15:12:08 +0300 Subject: [PATCH 02/97] add "time without finds" to afl-whatsup --- afl-whatsup | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/afl-whatsup b/afl-whatsup index 01edb210..c3017689 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -122,6 +122,7 @@ fmt_duration() FIRST=true TOTAL_WCOP= +TOTAL_LAST_PATH=0 for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do @@ -170,6 +171,10 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes)) TOTAL_PENDING=$((TOTAL_PENDING + pending_total)) TOTAL_PFAV=$((TOTAL_PFAV + pending_favs)) + + if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then + TOTAL_LAST_PATH=$last_path + fi if [ "$SUMMARY_ONLY" = "" ]; then @@ -236,6 +241,7 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24)) TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24)) test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available" +fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING test "$TOTAL_TIME" = "0" && TOTAL_TIME=1 @@ -262,6 +268,7 @@ fi echo " Crashes found : $TOTAL_CRASHES locally unique" echo "Cycles without finds : $TOTAL_WCOP" +echo " Time without finds : $TOTAL_LAST_PATH" echo exit 0 From c9a2401983bac38565120f0c73645bc88d2f2b25 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 24 Mar 2020 08:44:18 +0100 Subject: [PATCH 03/97] fix doc link --- examples/custom_mutators/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md index 93f824cd..e5af5516 100644 --- a/examples/custom_mutators/README.md +++ b/examples/custom_mutators/README.md @@ -1,7 +1,7 @@ # Examples for the custom mutator These are example and helper files for the custom mutator feature. -See [docs/python_mutators.md](../docs/custom_mutators.md) for more information +See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information Note that if you compile with python3.7 you must use python3 scripts, and if you use pyton2.7 to compile python2 scripts! From 50be709e91ef519f6614314e88cbe84581c41313 Mon Sep 17 00:00:00 2001 From: Ashis Kumar Singh <49238464+ashiscs@users.noreply.github.com> Date: Wed, 25 Mar 2020 01:21:02 +0530 Subject: [PATCH 04/97] fixed typos in README.md --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 5b2995d8..88e2b3c6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ * Win32 PE binary-only fuzzing with QEMU and Wine - * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly). + * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusively). * QBDI mode to fuzz android native libraries via QBDI framework @@ -85,7 +85,7 @@ (4) Only for LLVM >= 9 and not all targets compile - (5) upcoming, development in branch + (5) upcoming, development in the branch (6) not compatible with LTO and InsTrim modes @@ -118,13 +118,13 @@ We are happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)! :-) We have several ideas we would like to see in AFL++ to make it even better. -However we already work on so many things that we do not have the time for +However, we already work on so many things that we do not have the time for all the big ideas. This can be your way to support and contribute to AFL++ - extend it to something cool -We have an idea list in [docs/ideas.md](docs/ideas.md) +We have an idealist in [docs/ideas.md](docs/ideas.md) For everyone who wants to contribute (and send pull requests) please read [CONTRIBUTING.md](CONTRIBUTING.md) before your submit. @@ -205,9 +205,9 @@ There have been numerous attempts to solve this problem. One of the early approaches - pioneered by Tavis Ormandy - is corpus distillation. The method relies on coverage signals to select a subset of interesting seeds from a massive, high-quality corpus of candidate files, and then fuzz them by -traditional means. The approach works exceptionally well, but requires such +traditional means. The approach works exceptionally well but requires such a corpus to be readily available. In addition, block coverage measurements -provide only a very simplistic understanding of program state, and are less +provide only a very simplistic understanding of the program state and are less useful for guiding the fuzzing effort in the long haul. Other, more sophisticated research has focused on techniques such as program @@ -228,7 +228,7 @@ Simplifying a bit, the overall algorithm can be summed up as: 1) Load user-supplied initial test cases into the queue, - 2) Take next input file from the queue, + 2) Take the next input file from the queue, 3) Attempt to trim the test case to the smallest size that doesn't alter the measured behavior of the program, @@ -295,7 +295,7 @@ Using partial instrumentation is also recommended, see When testing libraries, you need to find or write a simple program that reads data from stdin or from a file and passes it to the tested library. In such a case, it is essential to link this executable against a static version of the -instrumented library, or to make sure that the correct .so file is loaded at +instrumented library or to make sure that the correct .so file is loaded at runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static build, usually possible via: @@ -316,7 +316,7 @@ file for important caveats. When source code is *NOT* available, the fuzzer offers experimental support for fast, on-the-fly instrumentation of black-box binaries. This is accomplished -with a version of QEMU running in the lesser-known "user space emulation" mode. +with a version of QEMU running in the lesser-known "userspace emulation" mode. QEMU is a project separate from AFL, but you can conveniently build the feature by doing: @@ -342,7 +342,7 @@ A more comprehensive description of these and other options can be found in ## Good examples and writeups -Here are some good writeups to show how to effectibly use AFL++: +Here are some good writeups to show how to effectively use AFL++: * [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/) * [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/) @@ -372,7 +372,7 @@ The available schedules are: - mmopt (experimental) - rare (experimental) -In parallel mode (-M/-S, several instances with shared queue), we suggest to +In parallel mode (-M/-S, several instances with the shared queue), we suggest to run the master using the explore or fast schedule (-p explore) and the slaves with a combination of cut-off-exponential (-p coe), exponential (-p fast), explore (-p explore) and mmopt (-p mmopt) schedules. If a schedule does @@ -380,7 +380,7 @@ not perform well for a target, restart the slave with a different schedule. In single mode, using -p fast is usually slightly more beneficial than the default explore mode. -(We don't want to change the default behaviour of afl, so "fast" has not been +(We don't want to change the default behavior of afl, so "fast" has not been made the default mode). More details can be found in the paper published at the 23rd ACM Conference on @@ -450,12 +450,12 @@ See the [docs/status_screen.md](docs/status_screen.md) file for information on how to interpret the displayed stats and monitor the health of the process. Be sure to consult this file especially if any UI elements are highlighted in red. -The fuzzing process will continue until you press Ctrl-C. At minimum, you want +The fuzzing process will continue until you press Ctrl-C. At a minimum, you want to allow the fuzzer to complete one queue cycle, which may take anywhere from a couple of hours to a week or so. There are three subdirectories created within the output directory and updated -in real time: +in real-time: - queue/ - test cases for every distinctive execution path, plus all the starting files given by the user. This is the synthesized corpus @@ -480,7 +480,7 @@ involve any state transitions not seen in previously-recorded faults. If a single bug can be reached in multiple ways, there will be some count inflation early in the process, but this should quickly taper off. -The file names for crashes and hangs are correlated with parent, non-faulting +The file names for crashes and hangs are correlated with the parent, non-faulting queue entries. This should help with debugging. When you can't reproduce a crash found by afl-fuzz, the most likely cause is @@ -544,10 +544,10 @@ instrumentation feedback alone. This actually works in practice, say: PS. Even when no explicit dictionary is given, afl-fuzz will try to extract existing syntax tokens in the input corpus by watching the instrumentation very closely during deterministic byte flips. This works for some types of -parsers and grammars, but isn't nearly as good as the -x mode. +parsers and grammars but isn't nearly as good as the -x mode. If a dictionary is really hard to come by, another option is to let AFL run -for a while, and then use the token capture library that comes as a companion +for a while and then use the token capture library that comes as a companion utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md). ## Crash triage @@ -562,7 +562,7 @@ difficult to quickly evaluate for exploitability without a lot of debugging and code analysis work. To assist with this task, afl-fuzz supports a very unique "crash exploration" mode enabled with the -C flag. -In this mode, the fuzzer takes one or more crashing test cases as the input, +In this mode, the fuzzer takes one or more crashing test cases as the input and uses its feedback-driven fuzzing strategies to very quickly enumerate all code paths that can be reached in the program while keeping it in the crashing state. @@ -601,7 +601,7 @@ near the end of [docs/technical_details.md](docs/technical_details.md). Fuzzing is a wonderful and underutilized technique for discovering non-crashing design and implementation errors, too. Quite a few interesting bugs have been -found by modifying the target programs to call abort() when, say: +found by modifying the target programs to call abort() when say: - Two bignum libraries produce different outputs when given the same fuzzer-generated input, @@ -623,7 +623,7 @@ shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL). ## Common-sense risks Please keep in mind that, similarly to many other computationally-intensive -tasks, fuzzing may put strain on your hardware and on the OS. In particular: +tasks, fuzzing may put a strain on your hardware and on the OS. In particular: - Your CPU will run hot and will need adequate cooling. In most cases, if cooling is insufficient or stops working properly, CPU speeds will be @@ -656,7 +656,7 @@ Here are some of the most important caveats for AFL: - AFL detects faults by checking for the first spawned process dying due to a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for these signals may need to have the relevant code commented out. In the same - vein, faults in child processed spawned by the fuzzed target may evade + vein, faults in child process spawned by the fuzzed target may evade detection unless you manually add some code to catch that. - As with any other brute-force tool, the fuzzer offers limited coverage if From 9c4d32b5b8d20b86afb2c59045baa63dd5a23031 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 24 Mar 2020 22:40:14 +0100 Subject: [PATCH 05/97] fixed call of custom mutators --- src/afl-fuzz-mutators.c | 6 +++--- src/afl-fuzz-one.c | 8 ++++---- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-run.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 0ded4ba1..3e6ad466 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -213,7 +213,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u8 * retbuf = NULL; size_t retlen = 0; - afl->mutator->afl_custom_trim(afl, &retbuf, &retlen); + afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf, &retlen); if (retlen > orig_len) FATAL( @@ -250,7 +250,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } /* Tell the custom mutator that the trimming was successful */ - afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 1); + afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 1); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", @@ -259,7 +259,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } else { /* Tell the custom mutator that the trimming was unsuccessful */ - afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 0); + afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, afl->stage_max); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index cc150cfe..bcd9135a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -360,7 +360,7 @@ u8 fuzz_one_original(afl_state_t *afl) { /* The custom mutator will decide to skip this test case or not. */ - if (!afl->mutator->afl_custom_queue_get(afl, afl->queue_cur->fname)) + if (!afl->mutator->afl_custom_queue_get(afl->mutator->data, afl->queue_cur->fname)) return 1; } @@ -1611,7 +1611,7 @@ custom_mutator_stage: close(fd); size_t mutated_size = afl->mutator->afl_custom_fuzz( - afl, &out_buf, len, new_buf, target->len, max_seed_size); + afl->mutator->data, &out_buf, len, new_buf, target->len, max_seed_size); ck_free(new_buf); @@ -1702,7 +1702,7 @@ havoc_stage: if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) { stacked_custom_prob = - afl->mutator->afl_custom_havoc_mutation_probability(afl); + afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data); if (stacked_custom_prob > 100) FATAL( "The probability returned by afl_custom_havoc_mutation_propability " @@ -1723,7 +1723,7 @@ havoc_stage: if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) { - temp_len = afl->mutator->afl_custom_havoc_mutation(afl, &out_buf, + temp_len = afl->mutator->afl_custom_havoc_mutation(afl->mutator->data, &out_buf, temp_len, MAX_FILE); } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f49e1f1e..b036969f 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -147,7 +147,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { /* At the initialization stage, queue_cur is NULL */ if (afl->queue_cur) fname_orig = afl->queue_cur->fname; - afl->mutator->afl_custom_queue_new_entry(afl, fname, fname_orig); + afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname, fname_orig); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 8c4b5941..2b207a9e 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -218,9 +218,9 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { u8 * new_data; size_t new_size = - afl->mutator->afl_custom_pre_save(afl, mem, len, &new_data); + afl->mutator->afl_custom_pre_save(afl->mutator->data, mem, len, &new_data); ck_write(fd, new_data, new_size, afl->fsrv.out_file); - ck_free(new_data); + free(new_data); } else { From f6466214c61e751455097378f97ce60b1970e9d3 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 25 Mar 2020 11:31:01 +0100 Subject: [PATCH 06/97] code format --- .../custom_mutators/custom_mutator_helpers.h | 11 +- examples/custom_mutators/example.c | 29 +++-- include/afl-fuzz.h | 19 ++- include/common.h | 25 ++-- llvm_mode/afl-clang-fast.c | 38 +++--- src/afl-fuzz-mutators.c | 22 ++-- src/afl-fuzz-one.c | 7 +- src/afl-fuzz-python.c | 46 ++++--- src/afl-fuzz-queue.c | 3 +- src/afl-fuzz-run.c | 8 +- src/afl-fuzz-stats.c | 119 +++++++++--------- 11 files changed, 175 insertions(+), 152 deletions(-) diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h index 844ccf94..cd3a15f0 100644 --- a/examples/custom_mutators/custom_mutator_helpers.h +++ b/examples/custom_mutators/custom_mutator_helpers.h @@ -7,11 +7,13 @@ #define RAND_BELOW(limit) (rand() % (limit)) -typedef struct{} afl_t; +typedef struct { + +} afl_t; static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { - static s8 interesting_8[] = {INTERESTING_8}; + static s8 interesting_8[] = {INTERESTING_8}; static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16}; static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32}; @@ -111,8 +113,8 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]; break; case 1: - *(u64 *)(out_buf + byte_idx) = - SWAP64((s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]); + *(u64 *)(out_buf + byte_idx) = SWAP64( + (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]); break; } @@ -266,3 +268,4 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { } #endif + diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 560a5919..2df17dec 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -23,7 +23,6 @@ static const char *commands[] = { }; - typedef struct my_mutator { afl_t *afl; @@ -34,21 +33,26 @@ typedef struct my_mutator { /** * Initialize this custom mutator * - * @param[in] afl a pointer to the internal state object. Can be ignored for now. - * @param[in] seed A seed for this mutator - the same seed should always mutate in the same way. + * @param[in] afl a pointer to the internal state object. Can be ignored for + * now. + * @param[in] seed A seed for this mutator - the same seed should always mutate + * in the same way. * @return Pointer to the data object this custom mutator instance should use. * There may be multiple instances of this mutator in one afl-fuzz run! * Returns NULL on error. */ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { - srand(seed); // needed also by surgical_havoc_mutate() + srand(seed); // needed also by surgical_havoc_mutate() my_mutator_t *data = calloc(1, sizeof(my_mutator_t)); if (!data) { + perror("afl_custom_init alloc"); return NULL; + } + data->afl = afl; return data; @@ -71,8 +75,8 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { */ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, uint8_t *add_buf, - size_t add_buf_size, // add_buf can be NULL - size_t max_size) { + size_t add_buf_size, // add_buf can be NULL + size_t max_size) { // Make sure that the packet size does not exceed the maximum size expected by // the fuzzer @@ -113,7 +117,8 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, * will release the memory after saving the test case. * @return Size of the output buffer after processing */ -size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { +size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, + uint8_t **out_buf) { size_t out_buf_size; @@ -183,7 +188,8 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { * the memory after saving the test case. * @param[out] out_buf_size Pointer to the size of the trimmed test case */ -void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size) { +void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, + size_t *out_buf_size) { *out_buf_size = trim_buf_size - 1; @@ -233,8 +239,8 @@ int afl_custom_post_trim(my_mutator_t *data, int success) { * not produce data larger than max_size. * @return Size of the mutated output. */ -size_t afl_custom_havoc_mutation(my_mutator_t *data, uint8_t **buf, size_t buf_size, - size_t max_size) { +size_t afl_custom_havoc_mutation(my_mutator_t *data, uint8_t **buf, + size_t buf_size, size_t max_size) { if (buf_size == 0) { @@ -292,7 +298,8 @@ uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) { * @param filename_new_queue File name of the new queue entry * @param filename_orig_queue File name of the original queue entry */ -void afl_custom_queue_new_entry(my_mutator_t *data, const uint8_t *filename_new_queue, +void afl_custom_queue_new_entry(my_mutator_t * data, + const uint8_t *filename_new_queue, const uint8_t *filename_orig_queue) { /* Additional analysis on the original or new test case */ diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7dddefb0..d610ac29 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -290,8 +290,8 @@ typedef struct py_mutator { PyObject *py_module; PyObject *py_functions[PY_FUNC_COUNT]; - void *afl_state; - void *py_data; + void * afl_state; + void * py_data; } py_mutator_t; @@ -592,7 +592,7 @@ struct custom_mutator { const char *name; void * dh; - void *data; /* custom mutator data ptr */ + void *data; /* custom mutator data ptr */ /* hooks for the custom mutator function */ @@ -620,8 +620,8 @@ struct custom_mutator { * not produce data larger than max_size. * @return Size of the mutated output. */ - size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size, - u8 *add_buf, size_t add_buf_size, size_t max_size); + size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size, u8 *add_buf, + size_t add_buf_size, size_t max_size); /** * A post-processing function to use right before AFL writes the test case to @@ -711,8 +711,8 @@ struct custom_mutator { * not produce data larger than max_size. * @return Size of the mutated output. */ - size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf, - size_t buf_size, size_t max_size); + size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf, size_t buf_size, + size_t max_size); /** * Return the probability (in percentage) that afl_custom_havoc_mutation @@ -748,9 +748,8 @@ struct custom_mutator { * @param filename_orig_queue File name of the original queue entry. This * argument can be NULL while initializing the fuzzer */ - void (*afl_custom_queue_new_entry)(void *data, - const u8 * filename_new_queue, - const u8 * filename_orig_queue); + void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue, + const u8 *filename_orig_queue); /** * Deinitialize the custom mutator. * diff --git a/include/common.h b/include/common.h index 97076004..8b21b55f 100644 --- a/include/common.h +++ b/include/common.h @@ -78,7 +78,7 @@ static u64 get_cur_time_us(void) { Will return buf for convenience. */ static u8 *stringify_int(u8 *buf, size_t len, u64 val) { - +\ #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ do { \ \ @@ -233,23 +233,22 @@ static u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { } - /* Unsafe Describe integer. The buf sizes are not checked. This is unsafe but fast. Will return buf for convenience. */ static u8 *u_stringify_int(u8 *buf, u64 val) { - -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ - do { \ - \ - if (val < (_divisor) * (_limit_mult)) { \ - \ - sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \ - return buf; \ - \ - } \ - \ +\ +#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ + do { \ + \ + if (val < (_divisor) * (_limit_mult)) { \ + \ + sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \ + return buf; \ + \ + } \ + \ } while (0) /* 0-9999 */ diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 34df5671..7050e22d 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -485,37 +485,37 @@ static void edit_params(u32 argc, char **argv) { // if (maybe_linking) { - if (x_set) { + if (x_set) { - cc_params[cc_par_cnt++] = "-x"; - cc_params[cc_par_cnt++] = "none"; + cc_params[cc_par_cnt++] = "-x"; + cc_params[cc_par_cnt++] = "none"; - } + } #ifndef __ANDROID__ - switch (bit_mode) { + switch (bit_mode) { - case 0: - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); - break; + case 0: + cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path); + break; - case 32: - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); + case 32: + cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m32 is not supported by your compiler"); - break; + break; - case 64: - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); + case 64: + cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + if (access(cc_params[cc_par_cnt - 1], R_OK)) + FATAL("-m64 is not supported by your compiler"); - break; + break; - } + } #endif diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 3e6ad466..0b0c3394 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -78,8 +78,7 @@ void destroy_custom_mutator(afl_state_t *afl) { afl->mutator->afl_custom_deinit(afl->mutator->data); - if (afl->mutator->dh) - dlclose(afl->mutator->dh); + if (afl->mutator->dh) dlclose(afl->mutator->dh); ck_free(afl->mutator); afl->mutator = NULL; @@ -103,11 +102,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* Mutator */ /* "afl_custom_init", required */ afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init"); - if (!afl->mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found."); + if (!afl->mutator->afl_custom_init) + FATAL("Symbol 'afl_custom_init' not found."); /* "afl_custom_deinit", required */ afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit"); - if (!afl->mutator->afl_custom_deinit) FATAL("Symbol 'afl_custom_deinit' not found."); + if (!afl->mutator->afl_custom_deinit) + FATAL("Symbol 'afl_custom_deinit' not found."); /* "afl_custom_fuzz" or "afl_custom_mutator", required */ afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz"); @@ -198,7 +199,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Initialize trimming in the custom mutator */ afl->stage_cur = 0; - afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); + afl->stage_max = + afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, @@ -206,7 +208,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { while (afl->stage_cur < afl->stage_max) { - sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec)); + sprintf(afl->stage_name_buf, "ptrim %s", + u_stringify_int(val_buf, trim_exec)); u32 cksum; @@ -250,7 +253,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } /* Tell the custom mutator that the trimming was successful */ - afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 1); + afl->stage_cur = + afl->mutator->afl_custom_post_trim(afl->mutator->data, 1); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", @@ -259,7 +263,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } else { /* Tell the custom mutator that the trimming was unsuccessful */ - afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); + afl->stage_cur = + afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, afl->stage_max); @@ -304,3 +309,4 @@ abort_trimming: return fault; } + diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index bcd9135a..7cc5e0d9 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -360,7 +360,8 @@ u8 fuzz_one_original(afl_state_t *afl) { /* The custom mutator will decide to skip this test case or not. */ - if (!afl->mutator->afl_custom_queue_get(afl->mutator->data, afl->queue_cur->fname)) + if (!afl->mutator->afl_custom_queue_get(afl->mutator->data, + afl->queue_cur->fname)) return 1; } @@ -1723,8 +1724,8 @@ havoc_stage: if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) { - temp_len = afl->mutator->afl_custom_havoc_mutation(afl->mutator->data, &out_buf, - temp_len, MAX_FILE); + temp_len = afl->mutator->afl_custom_havoc_mutation( + afl->mutator->data, &out_buf, temp_len, MAX_FILE); } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index d3027d2b..418497d0 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -29,8 +29,10 @@ #ifdef USE_PYTHON static void *unsupported(afl_state_t *afl, unsigned int seed) { + FATAL("Python Mutator cannot be called twice yet"); return NULL; + } size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf, @@ -77,7 +79,8 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf, PyTuple_SetItem(py_args, 2, py_value); - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args); Py_DECREF(py_args); @@ -99,7 +102,6 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf, } - static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { if (!module_name) return NULL; @@ -223,7 +225,8 @@ void finalize_py_module(void *py_mutator) { } -static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) { +static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, + unsigned int seed) { PyObject *py_args, *py_value; @@ -244,7 +247,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int see PyTuple_SetItem(py_args, 0, py_value); - py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args); + py_value = + PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args); Py_DECREF(py_args); @@ -289,9 +293,7 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) { py_mutator_t *py_mutator; py_mutator = init_py_module(afl, module_name); - if (!py_mutator) { - FATAL("Failed to load python mutator."); - } + if (!py_mutator) { FATAL("Failed to load python mutator."); } PyObject **py_functions = py_mutator->py_functions; @@ -334,7 +336,6 @@ 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 out_buf_size; @@ -350,7 +351,8 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) { PyTuple_SetItem(py_args, 0, py_value); - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args); Py_DECREF(py_args); @@ -386,7 +388,8 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) { PyTuple_SetItem(py_args, 0, py_value); - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -424,7 +427,8 @@ u32 post_trim_py(void *py_mutator, u8 success) { PyTuple_SetItem(py_args, 0, py_value); - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -451,7 +455,8 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) { PyObject *py_args, *py_value; py_args = PyTuple_New(0); - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -503,8 +508,9 @@ size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size, PyTuple_SetItem(py_args, 1, py_value); - py_value = - PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], + py_args); Py_DECREF(py_args); @@ -533,7 +539,9 @@ u8 havoc_mutation_probability_py(void *py_mutator) { py_args = PyTuple_New(0); py_value = PyObject_CallObject( - ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args); + ((py_mutator_t *)py_mutator) + ->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], + py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -573,7 +581,8 @@ u8 queue_get_py(void *py_mutator, const u8 *filename) { PyTuple_SetItem(py_args, 0, py_value); // Call Python function - py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -642,8 +651,9 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue, PyTuple_SetItem(py_args, 1, py_value); // Call - py_value = - PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args); + py_value = PyObject_CallObject( + ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], + py_args); Py_DECREF(py_args); if (py_value == NULL) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index b036969f..73da449a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -147,7 +147,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { /* At the initialization stage, queue_cur is NULL */ if (afl->queue_cur) fname_orig = afl->queue_cur->fname; - afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname, fname_orig); + afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname, + fname_orig); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2b207a9e..e8ef3049 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -217,8 +217,8 @@ 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); + 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); @@ -627,8 +627,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u32 remove_pos = remove_len; sprintf(afl->stage_name_buf, "trim %s/%s", - u_stringify_int(val_bufs[0], remove_len), - u_stringify_int(val_bufs[1], remove_len)); + u_stringify_int(val_bufs[0], remove_len), + u_stringify_int(val_bufs[1], remove_len)); afl->stage_cur = 0; afl->stage_max = q->len / remove_len; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index dc16df8f..5536c201 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -361,9 +361,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -406,8 +406,7 @@ void show_stats(afl_state_t *afl) { (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 || afl->in_bitmap || afl->crash_mode)) { - u_stringify_time_diff(time_tmp, cur_ms, - afl->last_path_time); + u_stringify_time_diff(time_tmp, cur_ms, afl->last_path_time); SAYF(bV bSTOP " last new path : " cRST "%-33s ", time_tmp); } else { @@ -446,9 +445,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -477,9 +476,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -533,30 +532,27 @@ void show_stats(afl_state_t *afl) { if (afl->stats_avg_exec < 100) { - sprintf(tmp, "%s/sec (%s)", - u_stringify_float(IB(0), afl->stats_avg_exec), - afl->stats_avg_exec < 20 ? "zzzz..." : "slow!"); + sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec), + afl->stats_avg_exec < 20 ? "zzzz..." : "slow!"); SAYF(bV bSTOP " exec speed : " cLRD "%-20s ", tmp); } else { - sprintf(tmp, "%s/sec", - u_stringify_float(IB(0), afl->stats_avg_exec)); + sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec)); SAYF(bV bSTOP " exec speed : " cRST "%-20s ", tmp); } - sprintf(tmp, "%s (%s%s unique)", - u_stringify_int(IB(0), afl->total_tmouts), - u_stringify_int(IB(1), afl->unique_tmouts), - (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_tmouts), + u_stringify_int(IB(1), afl->unique_tmouts), + (afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-22s" bSTG bV "\n", tmp); /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); @@ -567,12 +563,12 @@ void show_stats(afl_state_t *afl) { } else { sprintf(tmp, "%s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]), - u_stringify_int(IB(3), afl->stage_finds[STAGE_FLIP4]), - u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]), + u_stringify_int(IB(3), afl->stage_finds[STAGE_FLIP4]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4])); } @@ -582,12 +578,12 @@ void show_stats(afl_state_t *afl) { if (!afl->skip_deterministic) sprintf(tmp, "%s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]), - u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), - u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP " pending : " cRST "%-10s" bSTG bV "\n", @@ -595,12 +591,12 @@ void show_stats(afl_state_t *afl) { if (!afl->skip_deterministic) sprintf(tmp, "%s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]), - u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), - u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP " pend fav : " cRST "%-10s" bSTG bV "\n", @@ -621,25 +617,26 @@ void show_stats(afl_state_t *afl) { if (!afl->skip_deterministic) sprintf(tmp, "%s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]), - u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), - u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO])); SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP " imported : " cRST "%-10s" bSTG bV "\n", tmp, - afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a"); + afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) + : (u8 *)"n/a"); sprintf(tmp, "%s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]), - u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]), - u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]), - u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]), - u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]), - u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]), + u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]), + u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]), + u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]), + u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]), + u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA])); SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp); @@ -660,14 +657,14 @@ void show_stats(afl_state_t *afl) { if (afl->shm.cmplog_mode) { sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]), - u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]), - u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]), - u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]), - u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]), + u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]), + u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS])); SAYF(bV bSTOP " custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n", tmp); @@ -675,10 +672,10 @@ void show_stats(afl_state_t *afl) { } else { sprintf(tmp, "%s/%s, %s/%s", - u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), - u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]), - u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), - u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n", tmp); From 469446a02b48d3223b0964a013c352e6a189ad24 Mon Sep 17 00:00:00 2001 From: Ashis Kumar Singh <49238464+ashiscs@users.noreply.github.com> Date: Wed, 25 Mar 2020 19:35:38 +0530 Subject: [PATCH 07/97] updated with required changes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 88e2b3c6..781c8b49 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ all the big ideas. This can be your way to support and contribute to AFL++ - extend it to something cool -We have an idealist in [docs/ideas.md](docs/ideas.md) +We have an idea list in [docs/ideas.md](docs/ideas.md) For everyone who wants to contribute (and send pull requests) please read [CONTRIBUTING.md](CONTRIBUTING.md) before your submit. @@ -316,7 +316,7 @@ file for important caveats. When source code is *NOT* available, the fuzzer offers experimental support for fast, on-the-fly instrumentation of black-box binaries. This is accomplished -with a version of QEMU running in the lesser-known "userspace emulation" mode. +with a version of QEMU running in the lesser-known "user space emulation" mode. QEMU is a project separate from AFL, but you can conveniently build the feature by doing: @@ -656,7 +656,7 @@ Here are some of the most important caveats for AFL: - AFL detects faults by checking for the first spawned process dying due to a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for these signals may need to have the relevant code commented out. In the same - vein, faults in child process spawned by the fuzzed target may evade + vein, faults in child processes spawned by the fuzzed target may evade detection unless you manually add some code to catch that. - As with any other brute-force tool, the fuzzer offers limited coverage if From eeb7e12b9fcc8d9881c1825805371ebd5fcb10a8 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 25 Mar 2020 21:54:52 +0100 Subject: [PATCH 08/97] edited custom mutator pre_save api --- docs/custom_mutators.md | 2 +- examples/custom_mutators/example.c | 25 +++++++++----- include/afl-fuzz.h | 12 +++++-- src/afl-fuzz-mutators.c | 21 +++++++++++- src/afl-fuzz-python.c | 55 ++++++++++++++++++++++++++---- src/afl-fuzz-run.c | 52 +++++++++++++++++++++++----- 6 files changed, 140 insertions(+), 27 deletions(-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 14d8f518..ecbd50ba 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -30,7 +30,7 @@ C/C++: void afl_custom_init(unsigned int seed); size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf, size_t add_buf_size, size_t max_size); -size_t afl_custom_pre_save(uint8_t* buf, size_t buf_size, uint8_t** out_buf); +size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, uint8_t** out_buf); uint32_t afl_custom_init_trim(uint8_t* buf, size_t buf_size); void afl_custom_trim(uint8_t** out_buf, size_t* out_buf_size); uint32_t afl_custom_post_trim(uint8_t success); diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 2df17dec..3e708db8 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -12,6 +12,7 @@ #include #include #include +#include #define DATA_SIZE (100) @@ -112,21 +113,29 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case - * @param[out] out_buf Pointer to the buffer containing the test case after + * @param[in] out_buf Pointer to the buffer containing the test case after * processing. External library should allocate memory for out_buf. AFL++ * will release the memory after saving the test case. - * @return Size of the output buffer after processing + * out_buf will always be at least as large as buf. + * @param[in] out_buf_size The maximum size we may use. + * In case we need to have this bigger, simply return that. + * @return Size of the output buffer after processing or the needed amount. + * return 0 to indicate the original buf should be used. */ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, - uint8_t **out_buf) { + uint8_t *out_buf, size_t out_buf_size) { - size_t out_buf_size; + // In case we need more than out_buf_size, we return that amount and get + // called again. + if (out_buf_size < 32000) return 32000; + memcpy(out_buf, buf, buf_size); out_buf_size = buf_size; - - // External mutator should allocate memory for `out_buf` - *out_buf = malloc(out_buf_size); - memcpy(*out_buf, buf, out_buf_size); + out_buf[0] = 'A'; + out_buf[1] = 'F'; + out_buf[2] = 'L'; + out_buf[3] = '+'; + out_buf[4] = '+'; return out_buf_size; diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d610ac29..8bf66403 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -30,6 +30,9 @@ #define AFL_MAIN #define MESSAGES_TO_STDOUT +/* We preallocate a buffer of this size for afl_custom_pre_save */ +#define PRE_SAVE_BUF_INIT_SIZE (16384) + #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -293,6 +296,9 @@ typedef struct py_mutator { void * afl_state; void * py_data; + PyObject *scratch_buf; + size_t scratch_size; + } py_mutator_t; #endif @@ -591,6 +597,8 @@ struct custom_mutator { const char *name; void * dh; + u8 * pre_save_buf; + size_t pre_save_size; void *data; /* custom mutator data ptr */ @@ -639,7 +647,7 @@ struct custom_mutator { * @return Size of the output buffer after processing */ size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size, - u8 **out_buf); + u8 *out_buf, size_t out_buf_size); /** * This method is called at the start of each trimming operation and receives @@ -775,7 +783,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); void finalize_py_module(void *); -size_t pre_save_py(void *, u8 *, size_t, u8 **); +size_t pre_save_py(void *, u8 *, size_t, u8 *, size_t); u32 init_trim_py(void *, u8 *, size_t); u32 post_trim_py(void *, u8); void trim_py(void *, u8 **, size_t *); 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); From 68324353268cf02ab342d70ac3ba9b77f7059f30 Mon Sep 17 00:00:00 2001 From: Rishi Ranjan <43873720+rish9101@users.noreply.github.com> Date: Thu, 26 Mar 2020 23:17:48 +0530 Subject: [PATCH 09/97] Code Format (#275) --- src/afl-fuzz-stats.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 5536c201..53c162a2 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -361,9 +361,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -445,9 +445,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -476,9 +476,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -552,7 +552,7 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); From 97a1af39f7b6fb7de0320dd54116f5887dc13069 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 26 Mar 2020 19:44:44 +0100 Subject: [PATCH 10/97] more api --- docs/custom_mutators.md | 3 +- examples/custom_mutators/example.c | 35 ++++++++++++++++--- include/afl-fuzz.h | 19 +++++----- src/afl-fuzz-mutators.c | 11 +----- src/afl-fuzz-python.c | 56 ++++++++---------------------- src/afl-fuzz-run.c | 45 +++++------------------- src/afl-fuzz-stats.c | 14 ++++---- 7 files changed, 71 insertions(+), 112 deletions(-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index ecbd50ba..2163b2d5 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -27,7 +27,7 @@ performed with the custom mutator. C/C++: ```c -void afl_custom_init(unsigned int seed); +void afl_custom_init(void *afl, unsigned int seed); size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf, size_t add_buf_size, size_t max_size); size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, uint8_t** out_buf); @@ -39,6 +39,7 @@ uint8_t afl_custom_havoc_mutation_probability(void); uint8_t afl_custom_queue_get(const uint8_t* filename); void afl_custom_queue_new_entry(const uint8_t* filename_new_queue, const uint8_t* filename_orig_queue); +void afl_custom_deinit(void *data); ``` Python: diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 3e708db8..04b72c77 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -15,6 +15,7 @@ #include #define DATA_SIZE (100) +#define INITIAL_BUF_SIZE (16384) static const char *commands[] = { @@ -28,6 +29,8 @@ typedef struct my_mutator { afl_t *afl; // any additional data here! + size_t pre_save_size; + u8 * pre_save_buf; } my_mutator_t; @@ -56,6 +59,16 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { data->afl = afl; + data->pre_save_buf = malloc(INITIAL_BUF_SIZE); + if (!data->pre_save_buf) { + + free(data); + return NULL; + + } + + data->pre_save_size = INITIAL_BUF_SIZE; + return data; } @@ -125,12 +138,23 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t *out_buf, size_t out_buf_size) { - // In case we need more than out_buf_size, we return that amount and get - // called again. - if (out_buf_size < 32000) return 32000; + if (data->pre_save_size < buf_size + 5) { - memcpy(out_buf, buf, buf_size); - out_buf_size = buf_size; + data->pre_save_buf = realloc(data->pre_save_buf, buf_size + 5); + if (!data->pre_save_buf) { + + perror("custom mutator realloc"); + free(data); + return -1; + + } + + data->pre_save_size = buf_size + 5; + + } + + memcpy(out_buf + 5, buf, buf_size); + out_buf_size = buf_size + 5; out_buf[0] = 'A'; out_buf[1] = 'F'; out_buf[2] = 'L'; @@ -322,6 +346,7 @@ void afl_custom_queue_new_entry(my_mutator_t * data, */ void afl_custom_deinit(my_mutator_t *data) { + free(data->pre_save_buf); free(data); } diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 8bf66403..530a4b6a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -30,9 +30,6 @@ #define AFL_MAIN #define MESSAGES_TO_STDOUT -/* We preallocate a buffer of this size for afl_custom_pre_save */ -#define PRE_SAVE_BUF_INIT_SIZE (16384) - #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -296,8 +293,8 @@ typedef struct py_mutator { void * afl_state; void * py_data; - PyObject *scratch_buf; - size_t scratch_size; + u8 * pre_save_buf; + size_t pre_save_size; } py_mutator_t; @@ -641,13 +638,13 @@ struct custom_mutator { * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case - * @param[out] out_buf Pointer to the buffer of storing the test case after - * processing. External library should allocate memory for out_buf. AFL++ - * will release the memory after saving the test case. - * @return Size of the output buffer after processing + * @param[out] out_buf Pointer to the buffer storing the test case after + * processing. External library should allocate memory for out_buf. + * It can chose to alter buf in-place, if the space is large enough. + * @return Size of the output buffer. */ size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size, - u8 *out_buf, size_t out_buf_size); + u8 **out_buf); /** * This method is called at the start of each trimming operation and receives @@ -783,7 +780,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); void finalize_py_module(void *); -size_t pre_save_py(void *, u8 *, size_t, u8 *, size_t); +size_t pre_save_py(void *, u8 *, size_t, u8 **); u32 init_trim_py(void *, u8 *, size_t); u32 post_trim_py(void *, u8); void trim_py(void *, u8 **, size_t *); diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index fac97f8e..9d8610c0 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -135,18 +135,9 @@ 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 b053e8d5..6fbdb678 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -307,14 +307,8 @@ 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; @@ -344,39 +338,18 @@ 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 out_buf_size) { +size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) { - 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; - - } + size_t py_out_buf_size; + PyObject * py_args, *py_value; + py_mutator_t *py = (py_mutator_t *)py_mutator; py_args = PyTuple_New(1); py_value = PyByteArray_FromStringAndSize(buf, buf_size); if (!py_value) { Py_DECREF(py_args); - FATAL("Failed to convert arguments"); + FATAL("Failed to convert arguments in custom pre_save"); } @@ -390,25 +363,26 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 *out_buf, if (py_value != NULL) { py_out_buf_size = PyByteArray_Size(py_value); - if (py_out_buf_size > out_buf_size) { + + if (py_out_buf_size > py->pre_save_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; + Let's resize our buf */ + py->pre_save_buf = ck_realloc(py->pre_save_buf, py_out_buf_size); + py->pre_save_size = py_out_buf_size; } - memcpy(out_buf, PyByteArray_AsString(py_value), py_out_buf_size); + memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size); Py_DECREF(py_value); + + *out_buf = py->pre_save_buf; return py_out_buf_size; } else { PyErr_Print(); - FATAL("Call failed"); + FATAL("Python custom mutator: pre_save call failed."); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index a539b469..a43bfad2 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -214,47 +214,18 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { lseek(fd, 0, SEEK_SET); - if (afl->mutator && afl->mutator->afl_custom_pre_save) { + if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) { - if (unlikely(afl->mutator->pre_save_size < len)) { + u8 *new_buf = NULL; - afl->mutator->pre_save_buf = - ck_realloc(afl->mutator->pre_save_buf, len * sizeof(u8)); - afl->mutator->pre_save_size = len; + size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem, + len, &new_buf); - } + if (unlikely(new_size <= 0 || !new_buf)) + FATAL("Custom_pre_save failed (ret: %ld)", new_size); - 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); - - } - - } + /* everything as planned. use the new data. */ + ck_write(fd, new_buf, new_size, afl->fsrv.out_file); } else { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 53c162a2..5536c201 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -361,9 +361,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -445,9 +445,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -476,9 +476,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -552,7 +552,7 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); From 12a9a1001e76cd5c6e26eee9e16cbdd4f54b9b7a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 26 Mar 2020 19:47:16 +0100 Subject: [PATCH 11/97] docu --- examples/custom_mutators/example.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 04b72c77..220d0ca1 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -126,17 +126,14 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case - * @param[in] out_buf Pointer to the buffer containing the test case after - * processing. External library should allocate memory for out_buf. AFL++ - * will release the memory after saving the test case. - * out_buf will always be at least as large as buf. - * @param[in] out_buf_size The maximum size we may use. - * In case we need to have this bigger, simply return that. + * @param[out] out_buf Pointer to the buffer containing the test case after + * processing. External library should allocate memory for out_buf. + * The buf pointer may be reused (up to the given buf_size); * @return Size of the output buffer after processing or the needed amount. - * return 0 to indicate the original buf should be used. + * A return smaller 1 indicates an error. */ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, - uint8_t *out_buf, size_t out_buf_size) { + uint8_t **out_buf) { if (data->pre_save_size < buf_size + 5) { From 5a7d33330a2bbd4866138488b136dfd7bde3bf9b Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 26 Mar 2020 19:48:26 +0100 Subject: [PATCH 12/97] example fixed --- examples/custom_mutators/example.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 220d0ca1..8a45d87f 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -149,14 +149,15 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, data->pre_save_size = buf_size + 5; } + *out_buf = data->pre_save_buf; - memcpy(out_buf + 5, buf, buf_size); - out_buf_size = buf_size + 5; - out_buf[0] = 'A'; - out_buf[1] = 'F'; - out_buf[2] = 'L'; - out_buf[3] = '+'; - out_buf[4] = '+'; + memcpy(*out_buf + 5, buf, buf_size); + size_t out_buf_size = buf_size + 5; + *out_buf[0] = 'A'; + *out_buf[1] = 'F'; + *out_buf[2] = 'L'; + *out_buf[3] = '+'; + *out_buf[4] = '+'; return out_buf_size; From ae284610cf401fa9f533f553c445f003dcb70ec3 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 27 Mar 2020 10:08:09 +0100 Subject: [PATCH 13/97] important llvm_mode Makefile fix --- llvm_mode/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 9626665c..cdd24464 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -323,10 +323,10 @@ all_done: test_build install: all install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) ifndef AFL_TRACE_PC - if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi - if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-clang-lto -a -f ../afl-ld ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 ../afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi else - if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-clang-fast -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi endif if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi From a7553eae289ccaeb9626c650fa503ed04475c4f5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 27 Mar 2020 12:09:06 +0100 Subject: [PATCH 14/97] add CFI sanitizer --- README.md | 2 +- docs/Changelog.md | 1 + docs/env_variables.md | 4 +++- docs/notes_for_asan.md | 2 +- llvm_mode/LLVMInsTrim.so.cc | 1 + llvm_mode/afl-clang-fast.c | 21 ++++++++++++++++++-- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 1 + llvm_mode/afl-llvm-pass.so.cc | 1 + src/afl-common.c | 2 +- 9 files changed, 29 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 781c8b49..827a7aec 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,7 @@ superior to blind fuzzing or coverage-only tools. ## Instrumenting programs for use with AFL PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++ -instead of afl-gcc/afl-g++ is much faster and has a few cool features. +instead of afl-gcc/afl-g++ is much faster and has many cool features. See llvm_mode/ - however few code does not compile with llvm. We support llvm versions 3.8.0 to 11. diff --git a/docs/Changelog.md b/docs/Changelog.md index 6af269ce..198909d1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -31,6 +31,7 @@ sending a mail to . the last 5 queue entries - rare: puts focus on queue entries that hits rare branches, also ignores runtime + - llvm_mode: added Control Flow Integrity sanatizer (AFL_USE_CFISAN) - LTO collision free instrumented added in llvm_mode with afl-clang-lto - note that this mode is amazing, but quite some targets won't compile - Added llvm_mode NGRAM prev_loc coverage by Adrean Herrera diff --git a/docs/env_variables.md b/docs/env_variables.md index 98f27bdf..ae283b1c 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -31,7 +31,9 @@ tools make fairly broad use of environmental variables: (You can also enable MSAN via AFL_USE_MSAN; ASAN and MSAN come with the same gotchas; the modes are mutually exclusive. UBSAN can be enabled - similarly by setting the environment variable AFL_USE_UBSAN=1) + similarly by setting the environment variable AFL_USE_UBSAN=1. Finally + there is the Control Flow Integrity sanitizer that can be activated by + AFL_USE_CFISAN=1) - Setting AFL_CC, AFL_CXX, and AFL_AS lets you use alternate downstream compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md index b65873be..6a4806c0 100644 --- a/docs/notes_for_asan.md +++ b/docs/notes_for_asan.md @@ -29,7 +29,7 @@ Note that ASAN is incompatible with -static, so be mindful of that. (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) NOTE: if you run several slaves only one should run the target compiled with -ASAN (and UBSAN), the others should run the target with no sanitizers +ASAN (and UBSAN, CFISAN), the others should run the target with no sanitizers compiled in. There is also the option of generating a corpus using a non-ASAN binary, and diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index a94eb907..c4033523 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -513,6 +513,7 @@ struct InsTrim : public ModulePass { getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr, diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 7050e22d..c45c8799 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -135,7 +135,7 @@ static void find_obj(u8 *argv0) { /* Copy argv to cc_params, making the necessary edits. */ -static void edit_params(u32 argc, char **argv) { +static void edit_params(u32 argc, char **argv, char **envp) { u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0; u8 has_llvm_config = 0; @@ -395,6 +395,22 @@ static void edit_params(u32 argc, char **argv) { } + if (getenv("AFL_USE_CFISAN")) { + + if (!lto_mode) { + + uint32_t i = 0, found = 0; + while (envp[i] != NULL && !found) + if (strncmp("-flto", envp[i++], 5) == 0) + found = 1; + if (!found) cc_params[cc_par_cnt++] = "-flto"; + + } + cc_params[cc_par_cnt++] = "-fsanitize=cfi"; + cc_params[cc_par_cnt++] = "-fvisibility=hidden"; + + } + #ifdef USE_TRACE_PC if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || @@ -596,6 +612,7 @@ int main(int argc, char **argv, char **envp) { "AFL_USE_ASAN: activate address sanitizer\n" "AFL_USE_MSAN: activate memory sanitizer\n" "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" + "AFL_USE_CFISAN: activate control flow sanitizer\n" "AFL_LLVM_WHITELIST: enable whitelisting (selective " "instrumentation)\n" "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" @@ -685,7 +702,7 @@ int main(int argc, char **argv, char **envp) { find_obj(argv[0]); #endif - edit_params(argc, argv); + edit_params(argc, argv, envp); if (debug) { diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index febb8950..8bf485af 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -396,6 +396,7 @@ bool AFLLTOPass::runOnModule(Module &M) { getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %u locations with no collisions (on average %llu " "collisions would be in afl-gcc/afl-clang-fast) (%s mode).", diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index fefd9edd..e8f449b1 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -572,6 +572,7 @@ bool AFLCoverage::runOnModule(Module &M) { getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); OKF("Instrumented %u locations (%s mode, ratio %u%%).", inst_blocks, modeline, inst_ratio); diff --git a/src/afl-common.c b/src/afl-common.c index 8c4d53e8..e10de6b3 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -73,7 +73,7 @@ char * afl_environment_variables[] = { "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", - "AFL_USE_UBSAN", "AFL_WINE_PATH", NULL}; + "AFL_USE_UBSAN", "AFL_USE_CFISAN", "AFL_WINE_PATH", NULL}; void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { From 7c76b7db04b7068c3b52f3a0eeaf19d468425e79 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Fri, 27 Mar 2020 21:03:28 +0100 Subject: [PATCH 15/97] part1 make it compilable for llvm 3.8.0 (ubuntu 16.04) --- llvm_mode/afl-llvm-pass.so.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index e8f449b1..1c0a3c93 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -131,6 +131,20 @@ class AFLCoverage : public ModulePass { char AFLCoverage::ID = 0; +/* needed up to 3.9.0 */ +#if LLVM_VERSION_MAJOR == 3 && (LLVM_VERSION_MINOR < 9 || (LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1)) +uint64_t PowerOf2Ceil(unsigned in) { + uint64_t in64 = in - 1; + in64 |= (in64 >> 1); + in64 |= (in64 >> 2); + in64 |= (in64 >> 4); + in64 |= (in64 >> 8); + in64 |= (in64 >> 16); + in64 |= (in64 >> 32); + return in64 + 1; +} +#endif + bool AFLCoverage::runOnModule(Module &M) { LLVMContext &C = M.getContext(); From 14bd424d2a5854052c4c847b9d5eb435578c9774 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Mar 2020 21:59:08 +0100 Subject: [PATCH 16/97] almost --- include/afl-fuzz.h | 21 +++++++++ include/alloc-inl.h | 40 ++++++++++++++++ src/afl-fuzz-globals.c | 2 + src/afl-fuzz-one.c | 103 +++++++++++++++++------------------------ 4 files changed, 106 insertions(+), 60 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 530a4b6a..2154d860 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -583,6 +583,27 @@ typedef struct afl_state { u8 clean_trace_custom[MAP_SIZE]; u8 first_trace[MAP_SIZE]; +/*needed for afl_fuzz_one */ +// TODO: see which we can reuse + u8 *out_buf; + size_t out_size; + + u8 *out_scratch_buf; + size_t out_scratch_size; + + u8 *eff_buf; + size_t eff_size; + + u8 *in_buf; + size_t in_size; + + u8 *in_scratch_buf; + size_t in_scratch_size; + + u8 *ex_buf; + size_t ex_size; + + } afl_state_t; /* A global pointer to all instances is needed (for now) for signals to arrive diff --git a/include/alloc-inl.h b/include/alloc-inl.h index c8783d96..75b038c1 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -35,6 +35,9 @@ #include "types.h" #include "debug.h" +/* Initial size used for ck_maybe_grow */ +#define INITIAL_GROWTH_SIZE (64) + // Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators #ifndef _WANT_ORIGINAL_AFL_ALLOC @@ -764,5 +767,42 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, #endif /* _WANT_ORIGINAL_AFL_ALLOC */ +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will FATAL if size_needed is <1 or *size is negative. + @return For convenience, this function returns *buf. + */ +static inline void *ck_maybe_grow(void **buf, size_t *size, size_t size_needed) { + + /* Oops. found a bug? */ + if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); + + /* No need to realloc */ + if (likely(*size >= size_needed)) return *buf; + if (unlikely(*size < 0)) FATAL("Negative size detected!"); + /* No inital size was set */ + if (*size == 0) *size = INITIAL_GROWTH_SIZE; + while (*size < size_needed) { + *size *= 2; + } + *buf = ck_realloc(*buf, *size); + return *buf; + +} + +/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ +static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, size_t *size2) { + void *scratch_buf = *buf1; + size_t scratch_size = *size1; + *buf1 = *buf2; + *size1 = *size2; + *buf2 = scratch_buf; + *size2 = scratch_size; +} + +#undef INITIAL_GROWTH_SIZE + #endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c index 88633a1b..6de33596 100644 --- a/src/afl-fuzz-globals.c +++ b/src/afl-fuzz-globals.c @@ -79,6 +79,8 @@ list_t afl_states = {.element_prealloc_count = 0}; void afl_state_init(afl_state_t *afl) { + /* thanks to this memset, growing vars like out_buf + and out_size are NULL/0 by default. */ memset(afl, 0, sizeof(afl_state_t)); afl->w_init = 0.9; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 7cc5e0d9..6c1d69ad 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -347,6 +347,9 @@ u8 fuzz_one_original(afl_state_t *afl) { u8 a_collect[MAX_AUTO_EXTRA]; u32 a_len = 0; +/* Not pretty, but saves a lot of writing */ +#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + #ifdef IGNORE_FINDS /* In IGNORE_FINDS mode, skip any entries that weren't in the @@ -427,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) { single byte anyway, so it wouldn't give us any performance or memory usage benefits. */ - out_buf = ck_alloc_nozero(len); + out_buf = ck_maybe_grow((void **)&afl->out_buf, &afl->out_size, len); afl->subseq_tmouts = 0; @@ -719,7 +722,7 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Initialize effector map for the next step (see comments below). Always flag first and last byte as doing something. */ - eff_map = ck_alloc(EFF_ALEN(len)); + eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { @@ -1443,7 +1446,7 @@ skip_interest: orig_hit_cnt = new_hit_cnt; - ex_tmp = ck_alloc(len + MAX_DICT_FILE); + ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE); for (i = 0; i <= len; ++i) { @@ -1466,7 +1469,6 @@ skip_interest: if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) { - ck_free(ex_tmp); goto abandon_entry; } @@ -1480,8 +1482,6 @@ skip_interest: } - ck_free(ex_tmp); - new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; @@ -1607,14 +1607,16 @@ custom_mutator_stage: /* Read the additional testcase into a new buffer. */ fd = open(target->fname, O_RDONLY); if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname); - new_buf = ck_alloc_nozero(target->len); + + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len); ck_read(fd, new_buf, target->len, target->fname); close(fd); + // TODO: clean up this mess. size_t mutated_size = afl->mutator->afl_custom_fuzz( afl->mutator->data, &out_buf, len, new_buf, target->len, max_seed_size); - ck_free(new_buf); + if (mutated_size > len) afl->out_size = mutated_size; if (mutated_size > 0) { @@ -1642,7 +1644,7 @@ custom_mutator_stage: } - if (mutated_size < len) out_buf = ck_realloc(out_buf, len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); memcpy(out_buf, in_buf, len); } @@ -1955,7 +1957,7 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - new_buf = ck_alloc_nozero(temp_len + clone_len); + new_buf = ck_maybe_grow((void **)&afl->out_scratch_buf, &afl->out_scratch_size, temp_len + clone_len); /* Head */ @@ -1975,7 +1977,8 @@ havoc_stage: memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); - ck_free(out_buf); + + swap_bufs((void **)&afl->out_buf, &afl->out_size, (void **)&afl->out_scratch_buf, &afl->out_scratch_size); out_buf = new_buf; temp_len += clone_len; @@ -2069,7 +2072,7 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) break; - new_buf = ck_alloc_nozero(temp_len + extra_len); + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); /* Head */ memcpy(new_buf, out_buf, insert_at); @@ -2085,7 +2088,7 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) break; - new_buf = ck_alloc_nozero(temp_len + extra_len); + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); /* Head */ memcpy(new_buf, out_buf, insert_at); @@ -2099,7 +2102,7 @@ havoc_stage: memcpy(new_buf + insert_at + extra_len, out_buf + insert_at, temp_len - insert_at); - ck_free(out_buf); + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); out_buf = new_buf; temp_len += extra_len; @@ -2116,7 +2119,7 @@ havoc_stage: /* out_buf might have been mangled a bit, so let's restore it to its original size and shape. */ - if (temp_len < len) out_buf = ck_realloc(out_buf, len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); temp_len = len; memcpy(out_buf, in_buf, len); @@ -2178,7 +2181,6 @@ retry_splicing: if (in_buf != orig_in) { - ck_free(in_buf); in_buf = orig_in; len = afl->queue_cur->len; @@ -2222,7 +2224,7 @@ retry_splicing: if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname); - new_buf = ck_alloc_nozero(target->len); + new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len); ck_read(fd, new_buf, target->len, target->fname); @@ -2236,7 +2238,6 @@ retry_splicing: if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { - ck_free(new_buf); goto retry_splicing; } @@ -2249,10 +2250,10 @@ retry_splicing: len = target->len; memcpy(new_buf, in_buf, split_at); + swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch)); in_buf = new_buf; - ck_free(out_buf); - out_buf = ck_alloc_nozero(len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); memcpy(out_buf, in_buf, len); goto custom_mutator_stage; @@ -2280,12 +2281,14 @@ radamsa_stage: orig_hit_cnt = afl->queued_paths + afl->unique_crashes; - /* Read the additional testcase into a new buffer. */ - u8 *save_buf = ck_alloc_nozero(len); + /* Read the additional testcase. + We'll reuse in_scratch, as it is free at this point. + */ + u8 *save_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), len); memcpy(save_buf, out_buf, len); u32 max_len = len + choose_block_len(afl, HAVOC_BLK_XL); - u8 *new_buf = ck_alloc_nozero(max_len); + u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), max_len); u8 *tmp_buf; for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { @@ -2307,17 +2310,12 @@ radamsa_stage: if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { - ck_free(save_buf); - ck_free(new_buf); goto abandon_entry; } } - ck_free(save_buf); - ck_free(new_buf); - new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt; @@ -2347,10 +2345,6 @@ abandon_entry: munmap(orig_in, afl->queue_cur->len); - if (in_buf != orig_in) ck_free(in_buf); - ck_free(out_buf); - ck_free(eff_map); - return ret_val; #undef FLIP_BIT @@ -2449,7 +2443,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { single byte anyway, so it wouldn't give us any performance or memory usage benefits. */ - out_buf = ck_alloc_nozero(len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); afl->subseq_tmouts = 0; @@ -2728,7 +2722,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { /* Initialize effector map for the next step (see comments below). Always flag first and last byte as doing something. */ - eff_map = ck_alloc(EFF_ALEN(len)); + eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len)); eff_map[0] = 1; if (EFF_APOS(len - 1) != 0) { @@ -3452,7 +3446,7 @@ skip_interest: orig_hit_cnt = new_hit_cnt; - ex_tmp = ck_alloc(len + MAX_DICT_FILE); + ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE); for (i = 0; i <= len; ++i) { @@ -3475,7 +3469,6 @@ skip_interest: if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) { - ck_free(ex_tmp); goto abandon_entry; } @@ -3489,8 +3482,6 @@ skip_interest: } /* for i = 0; i <= len */ - ck_free(ex_tmp); - new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; @@ -3894,7 +3885,7 @@ pacemaker_fuzzing: clone_to = rand_below(afl, temp_len); - new_buf = ck_alloc_nozero(temp_len + clone_len); + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); /* Head */ @@ -3915,7 +3906,7 @@ pacemaker_fuzzing: memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); - ck_free(out_buf); + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); out_buf = new_buf; temp_len += clone_len; MOpt_globals.cycles_v2[STAGE_Clone75] += 1; @@ -3968,7 +3959,7 @@ pacemaker_fuzzing: /* out_buf might have been mangled a bit, so let's restore it to its original size and shape. */ - if (temp_len < len) out_buf = ck_realloc(out_buf, len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); temp_len = len; memcpy(out_buf, in_buf, len); @@ -4046,7 +4037,6 @@ pacemaker_fuzzing: if (in_buf != orig_in) { - ck_free(in_buf); in_buf = orig_in; len = afl->queue_cur->len; @@ -4091,7 +4081,7 @@ pacemaker_fuzzing: if (fd < 0) PFATAL("Unable to open '%s'", target->fname); - new_buf = ck_alloc_nozero(target->len); + new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len); ck_read(fd, new_buf, target->len, target->fname); @@ -4105,7 +4095,6 @@ pacemaker_fuzzing: if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { - ck_free(new_buf); goto retry_splicing_puppet; } @@ -4118,9 +4107,9 @@ pacemaker_fuzzing: len = target->len; memcpy(new_buf, in_buf, split_at); + swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch)); in_buf = new_buf; - ck_free(out_buf); - out_buf = ck_alloc_nozero(len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); memcpy(out_buf, in_buf, len); goto havoc_stage_puppet; @@ -4155,10 +4144,6 @@ pacemaker_fuzzing: munmap(orig_in, afl->queue_cur->len); - if (in_buf != orig_in) ck_free(in_buf); - ck_free(out_buf); - ck_free(eff_map); - if (afl->key_puppet == 1) { if (unlikely( @@ -4380,18 +4365,13 @@ u8 fuzz_one(afl_state_t *afl) { int key_val_lv = 0; #ifdef _AFL_DOCUMENT_MUTATIONS + + u8 path_buf[PATH_MAX]; if (afl->do_document == 0) { - char *fn = alloc_printf("%s/mutations", afl->out_dir); - if (fn) { - - afl->do_document = mkdir(fn, 0700); // if it exists we do not care - afl->do_document = 1; - ck_free(fn); - - } else - - PFATAL("malloc()"); + snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir); + afl->do_document = mkdir(path_buf, 0700); // if it exists we do not care + afl->do_document = 1; } else { @@ -4419,5 +4399,8 @@ u8 fuzz_one(afl_state_t *afl) { return key_val_lv; + +#undef BUF_PARAMS + } From 02659df6bab4f4ecaec432c6e359d227a5205627 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Mar 2020 23:06:57 +0100 Subject: [PATCH 17/97] not allocating paths anymore --- src/afl-fuzz-bitmap.c | 39 ++++++++++++++++++--------------------- src/afl-fuzz-globals.c | 7 +++++++ src/afl-fuzz-init.c | 13 ++++--------- src/afl-fuzz-queue.c | 27 +++++++++++---------------- 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0d5b542d..bb01ad21 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -31,13 +31,13 @@ void write_bitmap(afl_state_t *afl) { - u8 *fname; + u8 fname[PATH_MAX]; s32 fd; if (!afl->bitmap_changed) return; afl->bitmap_changed = 0; - fname = alloc_printf("%s/fuzz_bitmap", afl->out_dir); + snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) PFATAL("Unable to open '%s'", fname); @@ -45,7 +45,6 @@ void write_bitmap(afl_state_t *afl) { ck_write(fd, afl->virgin_bits, MAP_SIZE, fname); close(fd); - ck_free(fname); } @@ -462,14 +461,15 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { static void write_crash_readme(afl_state_t *afl) { - u8 * fn = alloc_printf("%s/crashes/README.txt", afl->out_dir); + u8 fn[PATH_MAX]; s32 fd; FILE *f; u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + sprintf(fn, "%s/crashes/README.txt", afl->out_dir); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - ck_free(fn); /* Do not die on errors here - that would be impolite. */ @@ -520,11 +520,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(len == 0)) return 0; - u8 *fn = ""; + u8 *queue_fn = ""; u8 hnb; s32 fd; u8 keeping = 0, res; + u8 fn[PATH_MAX]; + /* Update path frequency. */ u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); @@ -556,16 +558,16 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths, + queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths, describe_op(afl, hnb)); #else - fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); + queue_fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); #endif /* ^!SIMPLE_FILES */ - add_to_queue(afl, fn, len, 0); + add_to_queue(afl, queue_fn, len, 0); if (hnb == 2) { @@ -584,9 +586,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(res == FAULT_ERROR)) FATAL("Unable to execute target application"); - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn); - ck_write(fd, mem, len, fn); + fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn); + ck_write(fd, mem, len, queue_fn); close(fd); keeping = 1; @@ -642,12 +644,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - fn = alloc_printf("%s/hangs/id:%06llu,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, afl->unique_hangs, describe_op(afl, 0)); #else - fn = alloc_printf("%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs); + snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs); #endif /* ^!SIMPLE_FILES */ @@ -685,14 +687,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, - afl->unique_crashes, afl->kill_signal, - describe_op(afl, 0)); + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); #else - fn = alloc_printf("%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->unique_crashes, afl->kill_signal); + snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, afl->unique_crashes, afl->kill_signal); #endif /* ^!SIMPLE_FILES */ @@ -729,8 +728,6 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ck_write(fd, mem, len, fn); close(fd); - ck_free(fn); - return keeping; } diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c index 6de33596..3e573dd2 100644 --- a/src/afl-fuzz-globals.c +++ b/src/afl-fuzz-globals.c @@ -349,6 +349,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { void afl_state_deinit(afl_state_t *afl) { + free(afl->out_buf); + free(afl->out_scratch_buf); + free(afl->eff_buf); + free(afl->in_buf); + free(afl->in_scratch_buf); + free(afl->ex_buf); + list_remove(&afl_states, afl); } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 038c4393..1033c587 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -76,18 +76,17 @@ void bind_to_free_cpu(afl_state_t *afl) { while ((de = readdir(d))) { - u8 * fn; + u8 fn[PATH_MAX]; FILE *f; u8 tmp[MAX_LINE]; u8 has_vmsize = 0; if (!isdigit(de->d_name[0])) continue; - fn = alloc_printf("/proc/%s/status", de->d_name); + snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name); if (!(f = fopen(fn, "r"))) { - ck_free(fn); continue; } @@ -111,7 +110,6 @@ void bind_to_free_cpu(afl_state_t *afl) { } - ck_free(fn); fclose(f); } @@ -369,9 +367,9 @@ void read_testcases(afl_state_t *afl) { struct stat st; + u8 dfn[PATH_MAX]; + snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir, nl[i]->d_name); u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name); - u8 *dfn = alloc_printf("%s/.state/deterministic_done/%s", afl->in_dir, - nl[i]->d_name); u8 passed_det = 0; @@ -384,8 +382,6 @@ void read_testcases(afl_state_t *afl) { if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { - ck_free(fn2); - ck_free(dfn); continue; } @@ -401,7 +397,6 @@ void read_testcases(afl_state_t *afl) { and probably very time-consuming. */ if (!access(dfn, F_OK)) passed_det = 1; - ck_free(dfn); add_to_queue(afl, fn2, st.st_size, passed_det); diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 73da449a..b5ae1255 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -30,18 +30,15 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { - u8 *fn = strrchr(q->fname, '/'); + u8 fn[PATH_MAX]; s32 fd; - fn = alloc_printf("%s/queue/.state/deterministic_done/%s", afl->out_dir, - fn + 1); + snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, strrchr(q->fname, '/') + 1); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) PFATAL("Unable to create '%s'", fn); close(fd); - ck_free(fn); - q->passed_det = 1; } @@ -51,10 +48,13 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { - u8 *fn = strrchr(q->fname, '/') + 1, *ldest; + u8 fn[PATH_MAX]; + u8 ldest[PATH_MAX]; - ldest = alloc_printf("../../%s", fn); - fn = alloc_printf("%s/queue/.state/variable_behavior/%s", afl->out_dir, fn); + u8 *fn_name = strrchr(q->fname, '/') + 1; + + sprintf(ldest, "../../%s", fn_name); + sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name); if (symlink(ldest, fn)) { @@ -64,9 +64,6 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { } - ck_free(ldest); - ck_free(fn); - q->var_behavior = 1; } @@ -76,14 +73,13 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { - u8 *fn; + u8 fn[PATH_MAX]; if (state == q->fs_redundant) return; q->fs_redundant = state; - fn = strrchr(q->fname, '/'); - fn = alloc_printf("%s/queue/.state/redundant_edges/%s", afl->out_dir, fn + 1); + sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, strrchr(q->fname, '/') + 1); if (state) { @@ -99,8 +95,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } - ck_free(fn); - } /* Append new test case to the queue. */ @@ -114,6 +108,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { q->depth = afl->cur_depth + 1; q->passed_det = passed_det; q->n_fuzz = 1; + q->trace_mini = NULL; if (q->depth > afl->max_depth) afl->max_depth = q->depth; From 11414596077922dfccac6579df62d86bd7a758ef Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Mar 2020 23:23:11 +0100 Subject: [PATCH 18/97] less allocs --- src/afl-fuzz-stats.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 5536c201..d6403830 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -33,16 +33,16 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, struct rusage rus; unsigned long long int cur_time = get_cur_time(); - u8 * fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); + u8 fn[PATH_MAX]; s32 fd; FILE * f; + snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) PFATAL("Unable to create '%s'", fn); - ck_free(fn); - f = fdopen(fd, "w"); if (!f) PFATAL("fdopen() failed"); From e04f4b3f206c93d8c029d1ec2e9a7c08639a7acb Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 27 Mar 2020 23:30:15 +0100 Subject: [PATCH 19/97] code format --- examples/custom_mutators/example.c | 1 + include/afl-fuzz.h | 17 ++++++++--------- include/alloc-inl.h | 13 ++++++++++--- llvm_mode/afl-clang-fast.c | 10 +++++----- llvm_mode/afl-llvm-pass.so.cc | 7 ++++++- src/afl-fuzz-bitmap.c | 22 +++++++++++++--------- src/afl-fuzz-init.c | 11 ++++------- src/afl-fuzz-one.c | 30 +++++++++++++----------------- src/afl-fuzz-queue.c | 8 +++++--- src/afl-fuzz-stats.c | 2 +- 10 files changed, 66 insertions(+), 55 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 8a45d87f..4b0a461b 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -149,6 +149,7 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, data->pre_save_size = buf_size + 5; } + *out_buf = data->pre_save_buf; memcpy(*out_buf + 5, buf, buf_size); diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 2154d860..32eaf4af 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -583,27 +583,26 @@ typedef struct afl_state { u8 clean_trace_custom[MAP_SIZE]; u8 first_trace[MAP_SIZE]; -/*needed for afl_fuzz_one */ -// TODO: see which we can reuse - u8 *out_buf; + /*needed for afl_fuzz_one */ + // TODO: see which we can reuse + u8 * out_buf; size_t out_size; - u8 *out_scratch_buf; + u8 * out_scratch_buf; size_t out_scratch_size; - u8 *eff_buf; + u8 * eff_buf; size_t eff_size; - u8 *in_buf; + u8 * in_buf; size_t in_size; - u8 *in_scratch_buf; + u8 * in_scratch_buf; size_t in_scratch_size; - u8 *ex_buf; + u8 * ex_buf; size_t ex_size; - } afl_state_t; /* A global pointer to all instances is needed (for now) for signals to arrive diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 75b038c1..92d29c1e 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -774,7 +774,8 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, Will FATAL if size_needed is <1 or *size is negative. @return For convenience, this function returns *buf. */ -static inline void *ck_maybe_grow(void **buf, size_t *size, size_t size_needed) { +static inline void *ck_maybe_grow(void **buf, size_t *size, + size_t size_needed) { /* Oops. found a bug? */ if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); @@ -785,21 +786,27 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, size_t size_needed) /* No inital size was set */ if (*size == 0) *size = INITIAL_GROWTH_SIZE; while (*size < size_needed) { + *size *= 2; + } + *buf = ck_realloc(*buf, *size); return *buf; } /* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ -static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, size_t *size2) { - void *scratch_buf = *buf1; +static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, + size_t *size2) { + + void * scratch_buf = *buf1; size_t scratch_size = *size1; *buf1 = *buf2; *size1 = *size2; *buf2 = scratch_buf; *size2 = scratch_size; + } #undef INITIAL_GROWTH_SIZE diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index c45c8799..99bc8d03 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -397,15 +397,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (getenv("AFL_USE_CFISAN")) { - if (!lto_mode) { - + if (!lto_mode) { + uint32_t i = 0, found = 0; while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) - found = 1; + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; if (!found) cc_params[cc_par_cnt++] = "-flto"; - + } + cc_params[cc_par_cnt++] = "-fsanitize=cfi"; cc_params[cc_par_cnt++] = "-fvisibility=hidden"; diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 1c0a3c93..f6ead9ec 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -132,8 +132,11 @@ class AFLCoverage : public ModulePass { char AFLCoverage::ID = 0; /* needed up to 3.9.0 */ -#if LLVM_VERSION_MAJOR == 3 && (LLVM_VERSION_MINOR < 9 || (LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1)) +#if LLVM_VERSION_MAJOR == 3 && \ + (LLVM_VERSION_MINOR < 9 || \ + (LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1)) uint64_t PowerOf2Ceil(unsigned in) { + uint64_t in64 = in - 1; in64 |= (in64 >> 1); in64 |= (in64 >> 2); @@ -142,7 +145,9 @@ uint64_t PowerOf2Ceil(unsigned in) { in64 |= (in64 >> 16); in64 |= (in64 >> 32); return in64 + 1; + } + #endif bool AFLCoverage::runOnModule(Module &M) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index bb01ad21..8ca286b2 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -31,7 +31,7 @@ void write_bitmap(afl_state_t *afl) { - u8 fname[PATH_MAX]; + u8 fname[PATH_MAX]; s32 fd; if (!afl->bitmap_changed) return; @@ -461,7 +461,7 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { static void write_crash_readme(afl_state_t *afl) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX]; s32 fd; FILE *f; @@ -558,12 +558,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths, - describe_op(afl, hnb)); + queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, + afl->queued_paths, describe_op(afl, hnb)); #else - queue_fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); + queue_fn = + alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); #endif /* ^!SIMPLE_FILES */ @@ -645,11 +646,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, - afl->unique_hangs, describe_op(afl, 0)); + afl->unique_hangs, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs); + snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, + afl->unique_hangs); #endif /* ^!SIMPLE_FILES */ @@ -687,11 +689,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, + afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, afl->unique_crashes, afl->kill_signal); + snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, + afl->unique_crashes, afl->kill_signal); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1033c587..19092204 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -76,7 +76,7 @@ void bind_to_free_cpu(afl_state_t *afl) { while ((de = readdir(d))) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX]; FILE *f; u8 tmp[MAX_LINE]; u8 has_vmsize = 0; @@ -85,11 +85,7 @@ void bind_to_free_cpu(afl_state_t *afl) { snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name); - if (!(f = fopen(fn, "r"))) { - - continue; - - } + if (!(f = fopen(fn, "r"))) { continue; } while (fgets(tmp, MAX_LINE, f)) { @@ -368,7 +364,8 @@ void read_testcases(afl_state_t *afl) { struct stat st; u8 dfn[PATH_MAX]; - snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir, nl[i]->d_name); + snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir, + nl[i]->d_name); u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name); u8 passed_det = 0; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 6c1d69ad..c731ebc6 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1957,7 +1957,9 @@ havoc_stage: clone_to = rand_below(afl, temp_len); - new_buf = ck_maybe_grow((void **)&afl->out_scratch_buf, &afl->out_scratch_size, temp_len + clone_len); + new_buf = + ck_maybe_grow((void **)&afl->out_scratch_buf, + &afl->out_scratch_size, temp_len + clone_len); /* Head */ @@ -1977,8 +1979,8 @@ havoc_stage: memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); - - swap_bufs((void **)&afl->out_buf, &afl->out_size, (void **)&afl->out_scratch_buf, &afl->out_scratch_size); + swap_bufs((void **)&afl->out_buf, &afl->out_size, + (void **)&afl->out_scratch_buf, &afl->out_scratch_size); out_buf = new_buf; temp_len += clone_len; @@ -2072,7 +2074,8 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) break; - new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); + new_buf = + ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); /* Head */ memcpy(new_buf, out_buf, insert_at); @@ -2088,7 +2091,8 @@ havoc_stage: if (temp_len + extra_len >= MAX_FILE) break; - new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); + new_buf = + ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); /* Head */ memcpy(new_buf, out_buf, insert_at); @@ -2236,11 +2240,7 @@ retry_splicing: locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff); - if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { - - goto retry_splicing; - - } + if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; } /* Split somewhere between the first and last differing byte. */ @@ -2308,11 +2308,7 @@ radamsa_stage: } - if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { - - goto abandon_entry; - - } + if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { goto abandon_entry; } } @@ -3885,7 +3881,8 @@ pacemaker_fuzzing: clone_to = rand_below(afl, temp_len); - new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + temp_len + clone_len); /* Head */ @@ -4399,7 +4396,6 @@ u8 fuzz_one(afl_state_t *afl) { return key_val_lv; - #undef BUF_PARAMS } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index b5ae1255..4f1bd041 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -30,10 +30,11 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX]; s32 fd; - snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, strrchr(q->fname, '/') + 1); + snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, + strrchr(q->fname, '/') + 1); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) PFATAL("Unable to create '%s'", fn); @@ -79,7 +80,8 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { q->fs_redundant = state; - sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, strrchr(q->fname, '/') + 1); + sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, + strrchr(q->fname, '/') + 1); if (state) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index d6403830..7fde2fdc 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -33,7 +33,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, struct rusage rus; unsigned long long int cur_time = get_cur_time(); - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX]; s32 fd; FILE * f; From 18bc344cf522460772d6cca5917505e2958cb385 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 00:44:52 +0100 Subject: [PATCH 20/97] fixed leak --- include/alloc-inl.h | 2 ++ src/afl-fuzz-init.c | 1 + src/afl-fuzz-one.c | 10 +++++----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 92d29c1e..ed1e0397 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -788,10 +788,12 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, while (*size < size_needed) { *size *= 2; + if ((*size) < 0) FATAL("size_t overflow"); } *buf = ck_realloc(*buf, *size); + return *buf; } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 19092204..a69c3b61 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -379,6 +379,7 @@ void read_testcases(afl_state_t *afl) { if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { + free(fn2); continue; } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c731ebc6..024b4665 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -430,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) { single byte anyway, so it wouldn't give us any performance or memory usage benefits. */ - out_buf = ck_maybe_grow((void **)&afl->out_buf, &afl->out_size, len); + out_buf = ck_maybe_grow(BUF_PARAMS(out), len); afl->subseq_tmouts = 0; @@ -1958,8 +1958,7 @@ havoc_stage: clone_to = rand_below(afl, temp_len); new_buf = - ck_maybe_grow((void **)&afl->out_scratch_buf, - &afl->out_scratch_size, temp_len + clone_len); + ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); /* Head */ @@ -1979,9 +1978,9 @@ havoc_stage: memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); - swap_bufs((void **)&afl->out_buf, &afl->out_size, - (void **)&afl->out_scratch_buf, &afl->out_scratch_size); + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); out_buf = new_buf; + new_buf = NULL; temp_len += clone_len; } @@ -2108,6 +2107,7 @@ havoc_stage: swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); out_buf = new_buf; + new_buf = NULL; temp_len += extra_len; break; From 0059d167310911976a2ee5e89204d3d9f0fc5409 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 01:14:24 +0100 Subject: [PATCH 21/97] added nullptr fix by h1994st --- src/afl-fuzz-mutators.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 9d8610c0..41bc69c8 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -192,7 +192,7 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* Initialize the custom mutator */ if (afl->mutator->afl_custom_init) - afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); + afl->mutator->data = afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); } From 53fd8fe6ea6aa07247444dedc33e3b2491ec2334 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 04:57:44 +0100 Subject: [PATCH 22/97] more custom mutator remodelling --- .../custom_mutators/custom_mutator_helpers.h | 61 ++++++++++ examples/custom_mutators/example.c | 113 ++++++++++-------- examples/post_library/post_library.so.c | 84 +++++++++---- examples/post_library/post_library_png.so.c | 71 ++++++++--- include/afl-fuzz.h | 41 +++++-- src/afl-fuzz-cmplog.c | 9 +- src/afl-fuzz-globals.c | 2 + src/afl-fuzz-init.c | 14 ++- src/afl-fuzz-mutators.c | 24 ++-- src/afl-fuzz-one.c | 29 ++++- src/afl-fuzz-python.c | 64 ++++++---- src/afl-fuzz-run.c | 9 +- 12 files changed, 370 insertions(+), 151 deletions(-) diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h index cd3a15f0..0dc00d96 100644 --- a/examples/custom_mutators/custom_mutator_helpers.h +++ b/examples/custom_mutators/custom_mutator_helpers.h @@ -5,8 +5,18 @@ #include "types.h" #include +#define INITIAL_GROWTH_SIZE (64) + #define RAND_BELOW(limit) (rand() % (limit)) +/* Use in a struct: creates a name_buf and a name_size variable. */ +#define BUF_VAR(type, name) \ + type * name##_buf; \ + size_t name##_size; +/* this filles in `&structptr->something_buf, &structptr->something_size`. */ +#define BUF_PARAMS(struct, name) \ + (void **)&struct->name##_buf, &struct->name##_size + typedef struct { } afl_t; @@ -267,5 +277,56 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { } +/* This function makes sure *size is > size_needed after call. + It changes buf and size in-place, if needed. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will return NULL if size_needed is <1 or *size is negative or malloc Failed. + @return For convenience, this function returns *buf. NULL on error. + */ +static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { + + /* Oops. found a bug? */ + if (unlikely(size_needed < 1)) return NULL; + + /* No need to realloc */ + if (likely(*size >= size_needed)) return *buf; + if (unlikely(*size < 0)) return NULL; + /* No inital size was set */ + if (*size == 0) *size = INITIAL_GROWTH_SIZE; + while (*size < size_needed) { + + *size *= 2; + if ((*size) < 0) { + + /* An overflow occurred. Fall back to size_needed */ + *size = size_needed; + + } + + } + + *buf = realloc(*buf, *size); + + return *buf; + +} + +/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ +static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, + size_t *size2) { + + void * scratch_buf = *buf1; + size_t scratch_size = *size1; + *buf1 = *buf2; + *size1 = *size2; + *buf2 = scratch_buf; + *size2 = scratch_size; + +} + +#undef INITIAL_GROWTH_SIZE + #endif diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 4b0a461b..54fc9d47 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -15,7 +15,6 @@ #include #define DATA_SIZE (100) -#define INITIAL_BUF_SIZE (16384) static const char *commands[] = { @@ -28,9 +27,19 @@ static const char *commands[] = { typedef struct my_mutator { afl_t *afl; + // any additional data here! - size_t pre_save_size; - u8 * pre_save_buf; + uint8_t *trim_buf; + size_t trim_buf_size; + int trimmming_steps; + int cur_step; + + // Reused buffers: + BUF_VAR(u8, fuzz); + BUF_VAR(u8, data); + BUF_VAR(u8, havoc); + BUF_VAR(u8, trim_out); + BUF_VAR(u8, pre_save); } my_mutator_t; @@ -59,16 +68,6 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { data->afl = afl; - data->pre_save_buf = malloc(INITIAL_BUF_SIZE); - if (!data->pre_save_buf) { - - free(data); - return NULL; - - } - - data->pre_save_size = INITIAL_BUF_SIZE; - return data; } @@ -85,20 +84,25 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must not * produce data larger than max_size. - * @return Size of the mutated output. + * @return Size of the mutated output. Negative return will abort fuzzing. */ -size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, - uint8_t *add_buf, - size_t add_buf_size, // add_buf can be NULL - size_t max_size) { +size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, + u8 **out_buf, uint8_t *add_buf, + size_t add_buf_size, // add_buf can be NULL + size_t max_size) { // Make sure that the packet size does not exceed the maximum size expected by // the fuzzer size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size; - if (mutated_size > buf_size) *buf = realloc(*buf, mutated_size); + // maybe_grow is optimized to be quick for reused buffers. + u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size); + if (!mutated_out) { - uint8_t *mutated_out = *buf; + perror("custom mutator allocation (maybe_grow)"); + return -1; /* afl-fuzz will very likely error out after this. */ + + } // Randomly select a command string to add as a header to the packet memcpy(mutated_out, commands[rand() % 3], 3); @@ -112,6 +116,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size, } + *out_buf = mutated_out; return mutated_size; } @@ -137,11 +142,10 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, if (data->pre_save_size < buf_size + 5) { - data->pre_save_buf = realloc(data->pre_save_buf, buf_size + 5); + data->pre_save_buf = maybe_grow(BUF_PARAMS(data, pre_save), buf_size + 5); if (!data->pre_save_buf) { - perror("custom mutator realloc"); - free(data); + perror("custom mutator realloc failed."); return -1; } @@ -164,11 +168,6 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, } -static uint8_t *trim_buf; -static size_t trim_buf_size; -static int trimmming_steps; -static int cur_step; - /** * This method is called at the start of each trimming operation and receives * the initial buffer. It should return the amount of iteration steps possible @@ -193,20 +192,20 @@ static int cur_step; int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { // We simply trim once - trimmming_steps = 1; + data->trimmming_steps = 1; - cur_step = 0; - trim_buf = buf; - trim_buf_size = buf_size; + data->cur_step = 0; + data->trim_buf = buf; + data->trim_buf_size = buf_size; - return trimmming_steps; + return data->trimmming_steps; } /** * This method is called for each trimming operation. It doesn't have any * arguments because we already have the initial buffer from init_trim and we - * can memorize the current state in global variables. This can also save + * can memorize the current state in *data. This can also save * reparsing steps for each iteration. It should return the trimmed input * buffer, where the returned data must not exceed the initial input data in * length. Returning anything that is larger than the original data (passed @@ -216,19 +215,18 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { * * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[out] out_buf Pointer to the buffer containing the trimmed test case. - * External library should allocate memory for out_buf. AFL++ will release - * the memory after saving the test case. - * @param[out] out_buf_size Pointer to the size of the trimmed test case + * External library should allocate memory for out_buf. + * AFL++ will not release the memory after saving the test case. + * Keep a ref in *data. + * @return Pointer to the size of the trimmed test case */ -void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, - size_t *out_buf_size) { +size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) { - *out_buf_size = trim_buf_size - 1; + size_t ret = data->trim_buf_size - 1; - // External mutator should allocate memory for `out_buf` - *out_buf = malloc(*out_buf_size); + *out_buf = maybe_grow(BUF_PARAMS(data, trim_out), ret); // Remove the last byte of the trimming input - memcpy(*out_buf, trim_buf, *out_buf_size); + memcpy(*out_buf, data->trim_buf, ret); } @@ -248,12 +246,12 @@ int afl_custom_post_trim(my_mutator_t *data, int success) { if (success) { - ++cur_step; - return cur_step; + ++data->cur_step; + return data->cur_step; } - return trimmming_steps; + return data->trimmming_steps; } @@ -264,26 +262,33 @@ int afl_custom_post_trim(my_mutator_t *data, int success) { * (Optional) * * @param[in] data pointer returned in afl_custom_init for this fuzz case - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of input data + * @param[out] out_buf The output buffer. buf can be reused, if the content + * fits. * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. * @return Size of the mutated output. */ -size_t afl_custom_havoc_mutation(my_mutator_t *data, uint8_t **buf, - size_t buf_size, size_t max_size) { +size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size, + u8 **out_buf, size_t max_size) { if (buf_size == 0) { - *buf = realloc(*buf, 1); - **buf = rand() % 256; + *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1); + **out_buf = rand() % 256; buf_size = 1; + } else { + + // We reuse buf here. It's legal and faster. + *out_buf = buf; + } size_t victim = rand() % buf_size; - (*buf)[victim] += rand() % 10; + (*out_buf)[victim] += rand() % 10; return buf_size; @@ -346,6 +351,10 @@ void afl_custom_queue_new_entry(my_mutator_t * data, void afl_custom_deinit(my_mutator_t *data) { free(data->pre_save_buf); + free(data->havoc_buf); + free(data->data_buf); + free(data->fuzz_buf); + free(data->trim_out_buf); free(data); } diff --git a/examples/post_library/post_library.so.c b/examples/post_library/post_library.so.c index 5d2685cd..735aae9b 100644 --- a/examples/post_library/post_library.so.c +++ b/examples/post_library/post_library.so.c @@ -3,6 +3,7 @@ -------------------------------------------------- Originally written by Michal Zalewski + Edited by Dominik Maier, 2020 Copyright 2015 Google Inc. All rights reserved. @@ -41,22 +42,23 @@ AFL will call the afl_postprocess() function for every mutated output buffer. From there, you have three choices: - 1) If you don't want to modify the test case, simply return the original - buffer pointer ('in_buf'). + 1) If you don't want to modify the test case, simply set `*out_buf = in_buf` + and return the original `len`. 2) If you want to skip this test case altogether and have AFL generate a - new one, return NULL. Use this sparingly - it's faster than running - the target program with patently useless inputs, but still wastes CPU - time. + new one, return 0 or set `*out_buf = NULL`. + Use this sparingly - it's faster than running the target program + with patently useless inputs, but still wastes CPU time. 3) If you want to modify the test case, allocate an appropriately-sized buffer, move the data into that buffer, make the necessary changes, and - then return the new pointer. You can update *len if necessary, too. + then return the new pointer as out_buf. Return an appropriate len + afterwards. Note that the buffer will *not* be freed for you. To avoid memory leaks, you need to free it or reuse it on subsequent calls (as shown below). - *** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. *** + *** Feel free to reuse the original 'in_buf' BUFFER and return it. *** Aight. The example below shows a simple postprocessor that tries to make sure that all input files start with "GIF89a". @@ -74,47 +76,83 @@ #define HEADER "GIF89a" +typedef struct post_state { + + unsigned char *buf; + size_t size; + +} post_state_t; + +void *afl_postprocess_init(void *afl) { + + post_state_t *state = malloc(sizeof(post_state_t)); + if (!state) { + + perror("malloc"); + return NULL; + + } + + state->buf = calloc(sizeof(unsigned char), 4096); + if (!state->buf) { return NULL; } + + return state; + +} + /* The actual postprocessor routine called by afl-fuzz: */ -const unsigned char *afl_postprocess(const unsigned char *in_buf, - unsigned int * len) { - - static unsigned char *saved_buf; - unsigned char * new_buf; +size_t afl_postprocess(post_state_t *data, unsigned char *in_buf, + unsigned int len, unsigned char **out_buf) { /* Skip execution altogether for buffers shorter than 6 bytes (just to - show how it's done). We can trust *len to be sane. */ + show how it's done). We can trust len to be sane. */ - if (*len < strlen(HEADER)) return NULL; + if (len < strlen(HEADER)) return 0; /* Do nothing for buffers that already start with the expected header. */ - if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf; + if (!memcmp(in_buf, HEADER, strlen(HEADER))) { + + *out_buf = in_buf; + return len; + + } /* Allocate memory for new buffer, reusing previous allocation if possible. */ - new_buf = realloc(saved_buf, *len); + *out_buf = realloc(data->buf, len); /* If we're out of memory, the most graceful thing to do is to return the original buffer and give up on modifying it. Let AFL handle OOM on its own later on. */ - if (!new_buf) return in_buf; - saved_buf = new_buf; + if (!*out_buf) { + + *out_buf = in_buf; + return len; + + } /* Copy the original data to the new location. */ - memcpy(new_buf, in_buf, *len); + memcpy(*out_buf, in_buf, len); /* Insert the new header. */ - memcpy(new_buf, HEADER, strlen(HEADER)); + memcpy(*out_buf, HEADER, strlen(HEADER)); - /* Return modified buffer. No need to update *len in this particular case, - as we're not changing it. */ + /* Return the new len. It hasn't changed, so it's just len. */ - return new_buf; + return len; } +/* Gets called afterwards */ +void afl_postprocess_deinit(post_state_t *data) { + + free(data->buf); + free(data); + +} diff --git a/examples/post_library/post_library_png.so.c b/examples/post_library/post_library_png.so.c index 60ab318f..8597c88c 100644 --- a/examples/post_library/post_library_png.so.c +++ b/examples/post_library/post_library_png.so.c @@ -5,6 +5,7 @@ Originally written by Michal Zalewski Copyright 2015 Google Inc. All rights reserved. + Adapted to the new API, 2020 by Dominik Maier Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -35,11 +36,32 @@ #define UP4K(_i) ((((_i) >> 12) + 1) << 12) -const unsigned char *afl_postprocess(const unsigned char *in_buf, - unsigned int * len) { +typedef struct post_state { - static unsigned char *saved_buf; - static unsigned int saved_len; + unsigned char *buf; + size_t size; + +} post_state_t; + +void *afl_postprocess_init(void *afl) { + + post_state_t *state = malloc(sizeof(post_state_t)); + if (!state) { + + perror("malloc"); + return NULL; + + } + + state->buf = calloc(sizeof(unsigned char), 4096); + if (!state->buf) { return NULL; } + + return state; + +} + +size_t afl_postprocess(post_state_t *data, const unsigned char *in_buf, + unsigned int len, const unsigned char **out_buf) { unsigned char *new_buf = (unsigned char *)in_buf; unsigned int pos = 8; @@ -47,12 +69,17 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf, /* Don't do anything if there's not enough room for the PNG header (8 bytes). */ - if (*len < 8) return in_buf; + if (len < 8) { + + *out_buf = in_buf; + return len; + + } /* Minimum size of a zero-length PNG chunk is 12 bytes; if we don't have that, we can bail out. */ - while (pos + 12 <= *len) { + while (pos + 12 <= len) { unsigned int chunk_len, real_cksum, file_cksum; @@ -62,7 +89,7 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf, /* Bail out if chunk size is too big or goes past EOF. */ - if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > *len) break; + if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > len) break; /* Chunk checksum is calculated for chunk ID (dword) and the actual payload. */ @@ -82,17 +109,23 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf, if (new_buf == in_buf) { - if (*len <= saved_len) { + if (len <= data->size) { - new_buf = saved_buf; + new_buf = data->buf; } else { - new_buf = realloc(saved_buf, UP4K(*len)); - if (!new_buf) return in_buf; - saved_buf = new_buf; - saved_len = UP4K(*len); - memcpy(new_buf, in_buf, *len); + new_buf = realloc(data->buf, UP4K(len)); + if (!new_buf) { + + *out_buf = in_buf; + return len; + + } + + data->buf = new_buf; + data->size = UP4K(len); + memcpy(new_buf, in_buf, len); } @@ -108,7 +141,15 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf, } - return new_buf; + *out_buf = new_buf; + return len; } +/* Gets called afterwards */ +void afl_postprocess_deinit(post_state_t *data) { + + free(data->buf); + free(data); + +} diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 32eaf4af..5f9891bc 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -293,9 +293,18 @@ typedef struct py_mutator { void * afl_state; void * py_data; + u8 * fuzz_buf; + size_t fuzz_size; + u8 * pre_save_buf; size_t pre_save_size; + u8 * trim_buf; + size_t trim_size; + + u8 * havoc_buf; + size_t havoc_size; + } py_mutator_t; #endif @@ -544,7 +553,11 @@ typedef struct afl_state { struct extra_data *a_extras; /* Automatically selected extras */ u32 a_extras_cnt; /* Total number of tokens available */ - u8 *(*post_handler)(u8 *buf, u32 *len); + /* afl_postprocess API */ + void *(*post_init)(struct afl_state *afl); + size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf); + void *(*post_deinit)(void *data); + void *post_data; /* CmpLog */ @@ -643,10 +656,10 @@ struct custom_mutator { * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. - * @return Size of the mutated output. + * @return Size of the mutated output. Negative on error will abort exeuction. */ - size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size, u8 *add_buf, - size_t add_buf_size, size_t max_size); + size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf, + u8 *add_buf, size_t add_buf_size, size_t max_size); /** * A post-processing function to use right before AFL writes the test case to @@ -704,9 +717,9 @@ struct custom_mutator { * @param[out] out_buf Pointer to the buffer containing the trimmed test case. * External library should allocate memory for out_buf. AFL++ will release * the memory after saving the test case. - * @param[out] out_buf_size Pointer to the size of the trimmed test case + * @return the size of the trimmed test case */ - void (*afl_custom_trim)(void *data, u8 **out_buf, size_t *out_buf_size); + size_t (*afl_custom_trim)(void *data, u8 **out_buf); /** * This method is called after each trim operation to inform you if your @@ -728,16 +741,18 @@ struct custom_mutator { * * (Optional) * - * @param data pointer returned in afl_custom_init for this fuzz case - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of input data + * @param[out] out_buf The new buffer. It's legal to reuse *buf if it's < + * buf_size. * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. - * @return Size of the mutated output. + * @return Size of the mutated output (out_size). */ - size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf, size_t buf_size, - size_t max_size); + size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size, + u8 **out_buf, size_t max_size); /** * Return the probability (in percentage) that afl_custom_havoc_mutation @@ -803,8 +818,8 @@ void finalize_py_module(void *); size_t pre_save_py(void *, u8 *, size_t, u8 **); u32 init_trim_py(void *, u8 *, size_t); u32 post_trim_py(void *, u8); -void trim_py(void *, u8 **, size_t *); -size_t havoc_mutation_py(void *, u8 **, size_t, size_t); +size_t trim_py(void *, u8 **); +size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t); u8 havoc_mutation_probability_py(void *); u8 queue_get_py(void *, const u8 *); void queue_new_entry_py(void *, const u8 *, const u8 *); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 6c6f05ac..7c398507 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -527,8 +527,13 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { if (afl->post_handler) { - out_buf = afl->post_handler(out_buf, &len); - if (!out_buf || !len) return 0; + u8 *post_buf = NULL; + + size_t post_len = + afl->post_handler(afl->post_data, out_buf, len, &post_buf); + if (!post_buf || !post_len) return 0; + out_buf = post_buf; + len = post_len; } diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c index 3e573dd2..1d99e1fa 100644 --- a/src/afl-fuzz-globals.c +++ b/src/afl-fuzz-globals.c @@ -349,6 +349,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) { void afl_state_deinit(afl_state_t *afl) { + if (afl->post_deinit) afl->post_deinit(afl->post_data); + free(afl->out_buf); free(afl->out_scratch_buf); free(afl->eff_buf); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index a69c3b61..fe2be4d2 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -270,7 +270,9 @@ void setup_post(afl_state_t *afl) { void *dh; u8 * fn = afl->afl_env.afl_post_library; + u8 tbuf[6]; u32 tlen = 6; + strncpy(tbuf, "hello", tlen); if (!fn) return; @@ -281,10 +283,20 @@ void setup_post(afl_state_t *afl) { afl->post_handler = dlsym(dh, "afl_postprocess"); if (!afl->post_handler) FATAL("Symbol 'afl_postprocess' not found."); + afl->post_init = dlsym(dh, "afl_postprocess_init"); + if (!afl->post_init) FATAL("Symbol 'afl_postprocess_init' not found."); + afl->post_deinit = dlsym(dh, "afl_postprocess_deinit"); + if (!afl->post_deinit) FATAL("Symbol 'afl_postprocess_deinit' not found."); /* Do a quick test. It's better to segfault now than later =) */ - afl->post_handler("hello", &tlen); + u8 *post_buf = NULL; + afl->post_data = afl->post_init(afl); + if (!afl->post_data) FATAL("Could not initialize post handler."); + + size_t post_len = afl->post_handler(afl->post_data, tbuf, tlen, &post_buf); + if (!post_len || !post_buf) + SAYF("Empty return in test post handler for buf=\"hello\\0\"."); OKF("Postprocessor installed successfully."); diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 41bc69c8..0692ebb0 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -7,6 +7,7 @@ Now maintained by Marc Heuse , Heiko Eißfeldt and Andrea Fioraldi + Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. @@ -192,7 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* Initialize the custom mutator */ if (afl->mutator->afl_custom_init) - afl->mutator->data = afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); + afl->mutator->data = + afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); } @@ -218,17 +220,18 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { while (afl->stage_cur < afl->stage_max) { + u8 *retbuf = NULL; + sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec)); u32 cksum; - u8 * retbuf = NULL; - size_t retlen = 0; + size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf); - afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf, &retlen); - - if (retlen > orig_len) + if (unlikely(retlen < 0 || !retbuf)) + FATAL("custom_trim failed (ret %zd)", retlen); + else if (unlikely(retlen > orig_len)) FATAL( "Trimmed data returned by custom mutator is larger than original " "data"); @@ -238,12 +241,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = run_target(afl, afl->fsrv.exec_tmout); ++afl->trim_execs; - if (afl->stop_soon || fault == FAULT_ERROR) { - - ck_free(retbuf); - goto abort_trimming; - - } + if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; } cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); @@ -281,8 +279,6 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - ck_free(retbuf); - /* Since this can be slow, update the screen every now and then. */ if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 024b4665..8dfafb7b 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1612,15 +1612,20 @@ custom_mutator_stage: ck_read(fd, new_buf, target->len, target->fname); close(fd); - // TODO: clean up this mess. + u8 *mutated_buf = NULL; + size_t mutated_size = afl->mutator->afl_custom_fuzz( - afl->mutator->data, &out_buf, len, new_buf, target->len, max_seed_size); + afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len, + max_seed_size); + + if (unlikely(mutated_size < 0)) + FATAL("custom_fuzz returned %zd", mutated_size); if (mutated_size > len) afl->out_size = mutated_size; if (mutated_size > 0) { - if (common_fuzz_stuff(afl, out_buf, (u32)mutated_size)) { + if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) { goto abandon_entry; @@ -1726,8 +1731,22 @@ havoc_stage: if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) { - temp_len = afl->mutator->afl_custom_havoc_mutation( - afl->mutator->data, &out_buf, temp_len, MAX_FILE); + u8 * custom_havoc_buf = NULL; + size_t new_len = afl->mutator->afl_custom_havoc_mutation( + afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE); + if (unlikely(new_len < 0)) + FATAL("Error in custom_havoc (return %zd)", new_len); + if (likely(new_len > 0 && custom_havoc_buf)) { + + temp_len = new_len; + if (out_buf != custom_havoc_buf) { + + ck_maybe_grow(BUF_PARAMS(out), temp_len); + memcpy(out_buf, custom_havoc_buf, temp_len); + + } + + } } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 6fbdb678..f9f71929 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -35,15 +35,22 @@ static void *unsupported(afl_state_t *afl, unsigned int seed) { } -size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf, - size_t add_buf_size, size_t max_size) { +/* sorry for this makro... +it just filles in `&py_mutator->something_buf, &py_mutator->something_size`. */ +#define BUF_PARAMS(name) \ + (void **)&((py_mutator_t *)py_mutator)->name##_buf, \ + &((py_mutator_t *)py_mutator)->name##_size + +size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, + u8 *add_buf, size_t add_buf_size, size_t max_size) { size_t mutated_size; PyObject *py_args, *py_value; py_args = PyTuple_New(3); + py_mutator_t *py = (py_mutator_t *)py_mutator; /* buf */ - py_value = PyByteArray_FromStringAndSize(*buf, buf_size); + py_value = PyByteArray_FromStringAndSize(buf, buf_size); if (!py_value) { Py_DECREF(py_args); @@ -79,17 +86,17 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf, PyTuple_SetItem(py_args, 2, py_value); - py_value = PyObject_CallObject( - ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args); + py_value = PyObject_CallObject(py->py_functions[PY_FUNC_FUZZ], py_args); Py_DECREF(py_args); if (py_value != NULL) { mutated_size = PyByteArray_Size(py_value); - if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size); - memcpy(*buf, PyByteArray_AsString(py_value), mutated_size); + *out_buf = ck_maybe_grow(BUF_PARAMS(fuzz), mutated_size); + + memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size); Py_DECREF(py_value); return mutated_size; @@ -364,14 +371,8 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) { py_out_buf_size = PyByteArray_Size(py_value); - if (py_out_buf_size > py->pre_save_size) { - - /* Not enough space! - Let's resize our buf */ - py->pre_save_buf = ck_realloc(py->pre_save_buf, py_out_buf_size); - py->pre_save_size = py_out_buf_size; - - } + ck_maybe_grow((void **)&py->pre_save_buf, &py->pre_save_size, + py_out_buf_size); memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size); Py_DECREF(py_value); @@ -465,9 +466,10 @@ u32 post_trim_py(void *py_mutator, u8 success) { } -void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) { +size_t trim_py(void *py_mutator, u8 **out_buf) { PyObject *py_args, *py_value; + size_t ret; py_args = PyTuple_New(0); py_value = PyObject_CallObject( @@ -476,9 +478,9 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) { 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); + ret = PyByteArray_Size(py_value); + *out_buf = ck_maybe_grow(BUF_PARAMS(trim), ret); + memcpy(*out_buf, PyByteArray_AsString(py_value), ret); Py_DECREF(py_value); } else { @@ -488,17 +490,19 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) { } + return ret; + } -size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size, - size_t max_size) { +size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size, + u8 **out_buf, size_t max_size) { size_t mutated_size; PyObject *py_args, *py_value; py_args = PyTuple_New(2); /* buf */ - py_value = PyByteArray_FromStringAndSize(*buf, buf_size); + py_value = PyByteArray_FromStringAndSize(buf, buf_size); if (!py_value) { Py_DECREF(py_args); @@ -532,9 +536,19 @@ size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size, if (py_value != NULL) { mutated_size = PyByteArray_Size(py_value); - if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size); + if (mutated_size <= buf_size) { - memcpy(*buf, PyByteArray_AsString(py_value), mutated_size); + /* We reuse the input buf here. */ + *out_buf = buf; + + } else { + + /* A new buf is needed... */ + *out_buf = ck_maybe_grow(BUF_PARAMS(havoc), mutated_size); + + } + + memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size); Py_DECREF(py_value); return mutated_size; @@ -680,5 +694,7 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue, } +#undef BUF_PARAMS + #endif /* USE_PYTHON */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index a43bfad2..9ba2c5f7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -741,8 +741,13 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { if (afl->post_handler) { - out_buf = afl->post_handler(out_buf, &len); - if (!out_buf || !len) return 0; + u8 *post_buf = NULL; + + size_t post_len = + afl->post_handler(afl->post_data, out_buf, len, &post_buf); + if (!post_buf || !post_len) return 0; + out_buf = post_buf; + len = post_len; } From 8992c44c411174973528ca8874b8878e1109ca31 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 05:01:01 +0100 Subject: [PATCH 23/97] if exponential growth is too much, don't doo it --- examples/post_library/post_library.so.c | 1 + examples/post_library/post_library_png.so.c | 1 + include/alloc-inl.h | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/post_library/post_library.so.c b/examples/post_library/post_library.so.c index 735aae9b..0aa780cb 100644 --- a/examples/post_library/post_library.so.c +++ b/examples/post_library/post_library.so.c @@ -156,3 +156,4 @@ void afl_postprocess_deinit(post_state_t *data) { free(data); } + diff --git a/examples/post_library/post_library_png.so.c b/examples/post_library/post_library_png.so.c index 8597c88c..41ba4f5e 100644 --- a/examples/post_library/post_library_png.so.c +++ b/examples/post_library/post_library_png.so.c @@ -153,3 +153,4 @@ void afl_postprocess_deinit(post_state_t *data) { free(data); } + diff --git a/include/alloc-inl.h b/include/alloc-inl.h index ed1e0397..99a83413 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -788,7 +788,8 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, while (*size < size_needed) { *size *= 2; - if ((*size) < 0) FATAL("size_t overflow"); + /* in case of overflow we'll realloc to size_needed */ + if ((*size) < 0) *size = size_needed; } From 2a660b19a7a0e06e42e4d494cadf846501c60116 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 08:32:54 +0100 Subject: [PATCH 24/97] fix detection compiles (e.g. python) when using CFLAGS="-m32" --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 9913c603..fed33d57 100644 --- a/Makefile +++ b/Makefile @@ -36,20 +36,20 @@ SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8 ASAN_OPTIONS=detect_leaks=0 -ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" +ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_FLTO ?= -flto=full else - ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_FLTO ?= -flto=thin else - ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_FLTO ?= -flto endif endif endif ifneq "$(shell uname)" "Darwin" - ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_OPT = -march=native endif endif @@ -65,7 +65,7 @@ ifneq "$(shell uname -m)" "x86_64" endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -override CFLAGS += -Wall -g -Wno-pointer-sign -I include/ \ +override CFLAGS += -Wall -g -Wno-pointer-sign -I include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon @@ -133,7 +133,7 @@ endif COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h -ifeq "$(shell echo '$(HASH)include @int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" +ifeq "$(shell echo '$(HASH)include @int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" PYTHON_OK=1 PYFLAGS=-DUSE_PYTHON $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) -DPYTHON_VERSION="\"$(PYTHON_VERSION)\"" else @@ -163,7 +163,7 @@ ifdef PROFILING LDFLAGS+=-pg endif -ifeq "$(shell echo '$(HASH)include @$(HASH)include @int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1" +ifeq "$(shell echo '$(HASH)include @$(HASH)include @int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1" SHMAT_OK=1 else SHMAT_OK=0 @@ -226,7 +226,7 @@ test_x86: @echo "[*] Checking for the default compiler cc..." @type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC='."; echo; exit 1 ) @echo "[*] Checking for the ability to compile x86 code..." - @echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) + @echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) @rm -f .test1 else From a0dec909e76f492a7958050f101eebef1a998a44 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 08:38:50 +0100 Subject: [PATCH 25/97] fix warning in afl-fuzz-run, tested with '-m32' also --- src/afl-fuzz-run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 9ba2c5f7..315539d1 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -222,7 +222,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { len, &new_buf); if (unlikely(new_size <= 0 || !new_buf)) - FATAL("Custom_pre_save failed (ret: %ld)", new_size); + FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); /* everything as planned. use the new data. */ ck_write(fd, new_buf, new_size, afl->fsrv.out_file); From 4ad885001a0d05657562e2d89a6bbe60dae45fe0 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 09:31:30 +0100 Subject: [PATCH 26/97] making 'CFLAGS="-m32" make source-only tests' work --- gcc_plugin/Makefile | 12 +++++++++++- libdislocator/Makefile | 2 +- libtokencap/Makefile | 2 +- llvm_mode/LLVMInsTrim.so.cc | 2 +- llvm_mode/afl-llvm-pass.so.cc | 2 +- src/third_party/libradamsa/libradamsa.c | 2 +- test/test.sh | 2 +- 7 files changed, 17 insertions(+), 7 deletions(-) diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index 506d690d..df8bd9cb 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -29,7 +29,7 @@ MAN_PATH ?= $(PREFIX)/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -g -funroll-loops -CFLAGS += -Wall -I../include -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \ +override CFLAGS = -Wall -I../include -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \ -Wno-unused-function @@ -40,6 +40,16 @@ CXXEFLAGS := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2 CC ?= gcc CXX ?= g++ +ifeq "clang" "$(CC)" + CC = gcc + CXX = g++ +endif + +ifeq "clang++" "$(CXX)" + CC = gcc + CXX = g++ +endif + PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include" HASH=\# diff --git a/libdislocator/Makefile b/libdislocator/Makefile index 07d98a0d..3ee37088 100644 --- a/libdislocator/Makefile +++ b/libdislocator/Makefile @@ -19,7 +19,7 @@ HELPER_PATH = $(PREFIX)/lib/afl VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -funroll-loops -CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign +override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign ifdef USEHUGEPAGE CFLAGS += -DUSEHUGEPAGE diff --git a/libtokencap/Makefile b/libtokencap/Makefile index 4889479b..5fcd7731 100644 --- a/libtokencap/Makefile +++ b/libtokencap/Makefile @@ -21,7 +21,7 @@ MAN_PATH ?= $(PREFIX)/man/man8 VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -funroll-loops -CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign +override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign ifeq "$(shell uname)" "Linux" TARGETS = libtokencap.so diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index c4033523..8b23942c 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -509,7 +509,7 @@ struct InsTrim : public ModulePass { if (!be_quiet) { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index f6ead9ec..3b0e1fda 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -587,7 +587,7 @@ bool AFLCoverage::runOnModule(Module &M) { else { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", diff --git a/src/third_party/libradamsa/libradamsa.c b/src/third_party/libradamsa/libradamsa.c index f3677fa7..fe91594e 100644 --- a/src/third_party/libradamsa/libradamsa.c +++ b/src/third_party/libradamsa/libradamsa.c @@ -30815,7 +30815,7 @@ size_t copy_list(uint8_t *ptr, word lispval, size_t max) { lispval = G(lispval, 2); // list = cdr(list) } if (lispval != INULL && max == 0) { - printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", lispval); + printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", (unsigned long)lispval); } return n; } diff --git a/test/test.sh b/test/test.sh index 8434aaf1..ec4e71d0 100755 --- a/test/test.sh +++ b/test/test.sh @@ -580,7 +580,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { } $ECHO "$BLUE[*] Testing: shared library extensions" -cc -o test-compcov test-compcov.c > /dev/null 2>&1 +cc $CFLAGS -o test-compcov test-compcov.c > /dev/null 2>&1 test -e ../libtokencap.so && { AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1 grep -q BUGMENOT token.out > /dev/null 2>&1 && { From 0cff53785bd940ca75506d4c325e07a9ac833eba Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 09:54:40 +0100 Subject: [PATCH 27/97] llvm_mode: fix compiler warnings FORTIFY_SOURCE needs -O --- llvm_mode/Makefile | 8 ++++---- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index cdd24464..2bc5fce6 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -134,9 +134,9 @@ ifeq "$(AFL_REAL_LD)" "" endif endif -CFLAGS ?= -O3 -funroll-loops +CFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2 override CFLAGS = -Wall \ - -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \ + -g -Wno-pointer-sign -I ../include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \ -DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \ @@ -145,8 +145,8 @@ ifdef AFL_TRACE_PC CFLAGS += -DUSE_TRACE_PC=1 endif -CXXFLAGS ?= -O3 -funroll-loops -override CXXFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -I ../include/ \ +CXXFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2 +override CXXFLAGS += -Wall -g -I ../include/ \ -DVERSION=\"$(VERSION)\" -Wno-variadic-macros CLANG_CFL = `$(LLVM_CONFIG) --cxxflags` -Wl,-znodelete -fno-rtti -fpic $(CXXFLAGS) diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 8bf485af..4bc16f17 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -392,7 +392,7 @@ bool AFLLTOPass::runOnModule(Module &M) { else { char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s", + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", From 7a752d07959ac8350dbd1b18092ff369426fc905 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 10:00:23 +0100 Subject: [PATCH 28/97] gcc_plugin: fix compiler warnings regarding -O and FORTIFY_SOURCE --- gcc_plugin/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index df8bd9cb..4c7a0313 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -28,14 +28,14 @@ MAN_PATH ?= $(PREFIX)/man/man8 VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2) -CFLAGS ?= -O3 -g -funroll-loops -override CFLAGS = -Wall -I../include -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \ +CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2 +override CFLAGS = -Wall -I../include -Wno-pointer-sign \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \ -Wno-unused-function -CXXFLAGS ?= -O3 -g -funroll-loops -CXXEFLAGS := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2 +CXXFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2 +CXXEFLAGS := $(CXXFLAGS) -Wall CC ?= gcc CXX ?= g++ From fc46e9c9a0fb36fa7baeed9957f2c72a1318ec1e Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 10:23:11 +0100 Subject: [PATCH 29/97] alloc_inl.h/ck_maybe_grow(): fix compiler warning --- include/alloc-inl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 99a83413..ae908162 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -774,7 +774,7 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, Will FATAL if size_needed is <1 or *size is negative. @return For convenience, this function returns *buf. */ -static inline void *ck_maybe_grow(void **buf, size_t *size, +static inline void *ck_maybe_grow(void **buf, ssize_t *size, size_t size_needed) { /* Oops. found a bug? */ From 7a92bf974d716da8ccc9b7f89b4e18a909c849ad Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 11:01:29 +0100 Subject: [PATCH 30/97] alloc-inl.h/ck_maybe_grow() back to size_t, reimplement overflow check --- include/alloc-inl.h | 12 ++++++------ src/afl-fuzz-python.c | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index ae908162..11c1143a 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -771,10 +771,10 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, It will realloc *buf otherwise. *size will grow exponentially as per: https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ - Will FATAL if size_needed is <1 or *size is negative. + Will FATAL if size_needed is <1. @return For convenience, this function returns *buf. */ -static inline void *ck_maybe_grow(void **buf, ssize_t *size, +static inline void *ck_maybe_grow(void **buf, size_t *size, size_t size_needed) { /* Oops. found a bug? */ @@ -782,14 +782,14 @@ static inline void *ck_maybe_grow(void **buf, ssize_t *size, /* No need to realloc */ if (likely(*size >= size_needed)) return *buf; - if (unlikely(*size < 0)) FATAL("Negative size detected!"); - /* No inital size was set */ + + /* No initial size was set */ if (*size == 0) *size = INITIAL_GROWTH_SIZE; while (*size < size_needed) { - *size *= 2; /* in case of overflow we'll realloc to size_needed */ - if ((*size) < 0) *size = size_needed; + if (2*(*size) < size_needed) *size = size_needed; + else *size *= 2; } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index f9f71929..6f8982c0 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -36,7 +36,7 @@ static void *unsupported(afl_state_t *afl, unsigned int seed) { } /* sorry for this makro... -it just filles in `&py_mutator->something_buf, &py_mutator->something_size`. */ +it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */ #define BUF_PARAMS(name) \ (void **)&((py_mutator_t *)py_mutator)->name##_buf, \ &((py_mutator_t *)py_mutator)->name##_size @@ -371,8 +371,7 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) { py_out_buf_size = PyByteArray_Size(py_value); - ck_maybe_grow((void **)&py->pre_save_buf, &py->pre_save_size, - py_out_buf_size); + ck_maybe_grow(BUF_PARAMS(pre_save), py_out_buf_size); memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size); Py_DECREF(py_value); From 11767bec0e567db943e612b22d9ef4e25682b2b9 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 11:55:10 +0100 Subject: [PATCH 31/97] tiny changes in custom mut api --- examples/custom_mutators/example.c | 46 +++++++++++++++++++----------- include/afl-fuzz.h | 6 ++-- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 6 ++-- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-run.c | 2 +- 6 files changed, 39 insertions(+), 25 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 54fc9d47..9a62d1a7 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -29,16 +29,15 @@ typedef struct my_mutator { afl_t *afl; // any additional data here! - uint8_t *trim_buf; - size_t trim_buf_size; - int trimmming_steps; - int cur_step; + size_t trim_size_current; + int trimmming_steps; + int cur_step; // Reused buffers: BUF_VAR(u8, fuzz); BUF_VAR(u8, data); BUF_VAR(u8, havoc); - BUF_VAR(u8, trim_out); + BUF_VAR(u8, trim); BUF_VAR(u8, pre_save); } my_mutator_t; @@ -52,7 +51,7 @@ typedef struct my_mutator { * in the same way. * @return Pointer to the data object this custom mutator instance should use. * There may be multiple instances of this mutator in one afl-fuzz run! - * Returns NULL on error. + * Return NULL on error. */ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { @@ -80,11 +79,13 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) { * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Pointer to input data to be mutated * @param[in] buf_size Size of input data + * @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on + * error. * @param[in] add_buf Buffer containing the additional test case * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must not * produce data larger than max_size. - * @return Size of the mutated output. Negative return will abort fuzzing. + * @return Size of the mutated output. */ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, u8 **out_buf, uint8_t *add_buf, @@ -100,7 +101,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, if (!mutated_out) { perror("custom mutator allocation (maybe_grow)"); - return -1; /* afl-fuzz will very likely error out after this. */ + return 0; /* afl-fuzz will very likely error out after this. */ } @@ -135,7 +136,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, * processing. External library should allocate memory for out_buf. * The buf pointer may be reused (up to the given buf_size); * @return Size of the output buffer after processing or the needed amount. - * A return smaller 1 indicates an error. + * A return of 0 indicates an error. */ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { @@ -146,7 +147,8 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, if (!data->pre_save_buf) { perror("custom mutator realloc failed."); - return -1; + *out_buf = NULL; + return 0; } @@ -195,8 +197,11 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { data->trimmming_steps = 1; data->cur_step = 0; - data->trim_buf = buf; - data->trim_buf_size = buf_size; + + maybe_grow(BUF_PARAMS(data, trim), buf_size); + memcpy(data->trim_buf, buf, buf_size); + + data->trim_size_current = buf_size; return data->trimmming_steps; @@ -218,15 +223,15 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { * External library should allocate memory for out_buf. * AFL++ will not release the memory after saving the test case. * Keep a ref in *data. + * *out_buf = NULL is treated as error. * @return Pointer to the size of the trimmed test case */ size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) { - size_t ret = data->trim_buf_size - 1; + *out_buf = data->trim_buf; - *out_buf = maybe_grow(BUF_PARAMS(data, trim_out), ret); // Remove the last byte of the trimming input - memcpy(*out_buf, data->trim_buf, ret); + return data->trim_size_current - 1; } @@ -266,7 +271,7 @@ int afl_custom_post_trim(my_mutator_t *data, int success) { * output * @param[in] buf_size Size of input data * @param[out] out_buf The output buffer. buf can be reused, if the content - * fits. + * fits. *out_buf = NULL is treated as error. * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. * @return Size of the mutated output. @@ -277,6 +282,13 @@ size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size, if (buf_size == 0) { *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1); + if (!*out_buf) { + + perror("custom havoc: maybe_grow"); + return 0; + + } + **out_buf = rand() % 256; buf_size = 1; @@ -354,7 +366,7 @@ void afl_custom_deinit(my_mutator_t *data) { free(data->havoc_buf); free(data->data_buf); free(data->fuzz_buf); - free(data->trim_out_buf); + free(data->trim_buf); free(data); } diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 5f9891bc..79878cb6 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -649,14 +649,16 @@ struct custom_mutator { * (Optional for now. Required in the future) * * @param data pointer returned in afl_custom_init for this fuzz case - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of the input/output data + * @param[out] out_buf the new buffer. We may reuse *buf if large enough. + * *out_buf = NULL is treated as FATAL. * @param[in] add_buf Buffer containing the additional test case * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. - * @return Size of the mutated output. Negative on error will abort exeuction. + * @return Size of the mutated output. */ size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size); diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 0692ebb0..f14a57bb 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -229,7 +229,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf); - if (unlikely(retlen < 0 || !retbuf)) + if (unlikely(!retbuf)) FATAL("custom_trim failed (ret %zd)", retlen); else if (unlikely(retlen > orig_len)) FATAL( diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 8dfafb7b..b1bbad0a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1618,8 +1618,8 @@ custom_mutator_stage: afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len, max_seed_size); - if (unlikely(mutated_size < 0)) - FATAL("custom_fuzz returned %zd", mutated_size); + if (unlikely(!mutated_buf)) + FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size); if (mutated_size > len) afl->out_size = mutated_size; @@ -1734,7 +1734,7 @@ havoc_stage: u8 * custom_havoc_buf = NULL; size_t new_len = afl->mutator->afl_custom_havoc_mutation( afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE); - if (unlikely(new_len < 0)) + if (unlikely(!custom_havoc_buf)) FATAL("Error in custom_havoc (return %zd)", new_len); if (likely(new_len > 0 && custom_havoc_buf)) { diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 6f8982c0..76b5ca80 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -103,7 +103,7 @@ size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, } else { PyErr_Print(); - FATAL("Call failed"); + FATAL("python custom fuzz: call failed"); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 315539d1..90cb2ed5 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -221,7 +221,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem, len, &new_buf); - if (unlikely(new_size <= 0 || !new_buf)) + if (unlikely(!new_buf)) FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); /* everything as planned. use the new data. */ From 5625e059e1ca99bb6f82a619063cf9aebfdd0a95 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 12:15:01 +0100 Subject: [PATCH 32/97] alloc-inl.h/ck_maybe_grow(): restore original exponential allocs --- include/alloc-inl.h | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 11c1143a..b8c83db4 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -767,6 +767,20 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, #endif /* _WANT_ORIGINAL_AFL_ALLOC */ +/* This function calculates the lowest power of 2 greater or equal its argument. + @return The rounded up power of 2 (if no overflow) or 0 on overflow. +*/ +static inline size_t powerOf2Ceil(size_t in) { + if (in == 0 || in > (size_t)-1) return 0; /* avoid undefined behaviour under-/overflow */ + size_t out = in - 1; + out |= out >> 1; + out |= out >> 2; + out |= out >> 4; + out |= out >> 8; + out |= out >> 16; + return out + 1; +} + /* This function makes sure *size is > size_needed after call. It will realloc *buf otherwise. *size will grow exponentially as per: @@ -784,16 +798,19 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, if (likely(*size >= size_needed)) return *buf; /* No initial size was set */ - if (*size == 0) *size = INITIAL_GROWTH_SIZE; - while (*size < size_needed) { + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; - /* in case of overflow we'll realloc to size_needed */ - if (2*(*size) < size_needed) *size = size_needed; - else *size *= 2; + /* grow exponentially */ + size_t next_size = powerOf2Ceil(size_needed); + /* handle overflow */ + if (!next_size) { + next_size = size_needed; } - *buf = ck_realloc(*buf, *size); + /* alloc */ + *buf = ck_realloc(*buf, next_size); + *size = next_size; return *buf; From 4c11ef5d20ee84be91ceaceb432b7a67fb089484 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 12:58:56 +0100 Subject: [PATCH 33/97] error handling for custom mutators --- .../custom_mutators/custom_mutator_helpers.h | 49 ++++++++++++------- examples/custom_mutators/example.c | 15 ++++-- include/afl-fuzz.h | 13 ++--- include/alloc-inl.h | 6 +-- src/afl-fuzz-mutators.c | 3 +- src/afl-fuzz-python.c | 4 +- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h index 0dc00d96..e5ce3569 100644 --- a/examples/custom_mutators/custom_mutator_helpers.h +++ b/examples/custom_mutators/custom_mutator_helpers.h @@ -277,37 +277,48 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { } + +/* This function calculates the next power of 2 greater or equal its argument. + @return The rounded up power of 2 (if no overflow) or 0 on overflow. +*/ +static inline size_t next_pow2(size_t in) { + if (in == 0 || in > (size_t)-1) return 0; /* avoid undefined behaviour under-/overflow */ + size_t out = in - 1; + out |= out >> 1; + out |= out >> 2; + out |= out >> 4; + out |= out >> 8; + out |= out >> 16; + return out + 1; +} + /* This function makes sure *size is > size_needed after call. - It changes buf and size in-place, if needed. It will realloc *buf otherwise. *size will grow exponentially as per: https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ - Will return NULL if size_needed is <1 or *size is negative or malloc Failed. - @return For convenience, this function returns *buf. NULL on error. + Will return NULL and free *buf if size_needed is <1 or realloc failed. + @return For convenience, this function returns *buf. */ -static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { - - /* Oops. found a bug? */ - if (unlikely(size_needed < 1)) return NULL; +static inline void *maybe_grow(void **buf, size_t *size, + size_t size_needed) { /* No need to realloc */ - if (likely(*size >= size_needed)) return *buf; - if (unlikely(*size < 0)) return NULL; - /* No inital size was set */ - if (*size == 0) *size = INITIAL_GROWTH_SIZE; - while (*size < size_needed) { + if (likely(size_needed && *size >= size_needed)) return *buf; - *size *= 2; - if ((*size) < 0) { + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; - /* An overflow occurred. Fall back to size_needed */ - *size = size_needed; - - } + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + /* handle overflow */ + if (!next_size) { + next_size = size_needed; } - *buf = realloc(*buf, *size); + /* alloc */ + *buf = realloc(*buf, next_size); + *size = *buf ? next_size : 0; return *buf; diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 9a62d1a7..488ece81 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -100,6 +100,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size); if (!mutated_out) { + *out_buf = NULL; perror("custom mutator allocation (maybe_grow)"); return 0; /* afl-fuzz will very likely error out after this. */ @@ -189,16 +190,20 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, * @param data pointer returned in afl_custom_init for this fuzz case * @param buf Buffer containing the test case * @param buf_size Size of the test case - * @return The amount of possible iteration steps to trim the input + * @return The amount of possible iteration steps to trim the input. + * negative on error. */ -int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { +int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { // We simply trim once data->trimmming_steps = 1; data->cur_step = 0; - maybe_grow(BUF_PARAMS(data, trim), buf_size); + if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) { + perror("init_trim grow"); + return -1; + } memcpy(data->trim_buf, buf, buf_size); data->trim_size_current = buf_size; @@ -245,9 +250,9 @@ size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) { * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param success Indicates if the last trim operation was successful. * @return The next trim iteration index (from 0 to the maximum amount of - * steps returned in init_trim) + * steps returned in init_trim). negative ret on failure. */ -int afl_custom_post_trim(my_mutator_t *data, int success) { +int32_t afl_custom_post_trim(my_mutator_t *data, int success) { if (success) { diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 79878cb6..a265c1a3 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -700,9 +700,10 @@ struct custom_mutator { * @param data pointer returned in afl_custom_init for this fuzz case * @param buf Buffer containing the test case * @param buf_size Size of the test case - * @return The amount of possible iteration steps to trim the input + * @return The amount of possible iteration steps to trim the input. + * Negative on error. */ - u32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size); + s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size); /** * This method is called for each trimming operation. It doesn't have any @@ -733,9 +734,9 @@ struct custom_mutator { * @param data pointer returned in afl_custom_init for this fuzz case * @param success Indicates if the last trim operation was successful. * @return The next trim iteration index (from 0 to the maximum amount of - * steps returned in init_trim) + * steps returned in init_trim). Negative on error. */ - u32 (*afl_custom_post_trim)(void *data, u8 success); + s32 (*afl_custom_post_trim)(void *data, u8 success); /** * Perform a single custom mutation on a given input. @@ -818,8 +819,8 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); void finalize_py_module(void *); size_t pre_save_py(void *, u8 *, size_t, u8 **); -u32 init_trim_py(void *, u8 *, size_t); -u32 post_trim_py(void *, u8); +s32 init_trim_py(void *, u8 *, size_t); +s32 post_trim_py(void *, u8); size_t trim_py(void *, u8 **); size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t); u8 havoc_mutation_probability_py(void *); diff --git a/include/alloc-inl.h b/include/alloc-inl.h index b8c83db4..91564932 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -767,10 +767,10 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, #endif /* _WANT_ORIGINAL_AFL_ALLOC */ -/* This function calculates the lowest power of 2 greater or equal its argument. +/* This function calculates the next power of 2 greater or equal its argument. @return The rounded up power of 2 (if no overflow) or 0 on overflow. */ -static inline size_t powerOf2Ceil(size_t in) { +static inline size_t next_pow2(size_t in) { if (in == 0 || in > (size_t)-1) return 0; /* avoid undefined behaviour under-/overflow */ size_t out = in - 1; out |= out >> 1; @@ -801,7 +801,7 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; /* grow exponentially */ - size_t next_size = powerOf2Ceil(size_needed); + size_t next_size = next_pow2(size_needed); /* handle overflow */ if (!next_size) { diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index f14a57bb..90d7de40 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -213,7 +213,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { afl->stage_cur = 0; afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); - + if (unlikely(afl->stage_max) < 0) FATAL("custom_init_trim error ret: %d", afl->stage_max); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, q->len); @@ -273,6 +273,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Tell the custom mutator that the trimming was unsuccessful */ afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); + if (unlikely(afl->stage_cur < 0)) FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, afl->stage_max); diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 76b5ca80..91e5b084 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -388,7 +388,7 @@ size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) { } -u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) { +s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) { PyObject *py_args, *py_value; @@ -426,7 +426,7 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) { } -u32 post_trim_py(void *py_mutator, u8 success) { +s32 post_trim_py(void *py_mutator, u8 success) { PyObject *py_args, *py_value; From 1938a122226bdecfed8420d21eeb2b240bff1b6a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 12:59:41 +0100 Subject: [PATCH 34/97] code format --- examples/custom_mutators/custom_mutator_helpers.h | 13 ++++++------- examples/custom_mutators/example.c | 6 +++++- include/alloc-inl.h | 9 +++++---- src/afl-fuzz-mutators.c | 6 ++++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h index e5ce3569..0848321f 100644 --- a/examples/custom_mutators/custom_mutator_helpers.h +++ b/examples/custom_mutators/custom_mutator_helpers.h @@ -277,12 +277,13 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) { } - /* This function calculates the next power of 2 greater or equal its argument. @return The rounded up power of 2 (if no overflow) or 0 on overflow. */ static inline size_t next_pow2(size_t in) { - if (in == 0 || in > (size_t)-1) return 0; /* avoid undefined behaviour under-/overflow */ + + if (in == 0 || in > (size_t)-1) + return 0; /* avoid undefined behaviour under-/overflow */ size_t out = in - 1; out |= out >> 1; out |= out >> 2; @@ -290,6 +291,7 @@ static inline size_t next_pow2(size_t in) { out |= out >> 8; out |= out >> 16; return out + 1; + } /* This function makes sure *size is > size_needed after call. @@ -299,8 +301,7 @@ static inline size_t next_pow2(size_t in) { Will return NULL and free *buf if size_needed is <1 or realloc failed. @return For convenience, this function returns *buf. */ -static inline void *maybe_grow(void **buf, size_t *size, - size_t size_needed) { +static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { /* No need to realloc */ if (likely(size_needed && *size >= size_needed)) return *buf; @@ -312,9 +313,7 @@ static inline void *maybe_grow(void **buf, size_t *size, size_t next_size = next_pow2(size_needed); /* handle overflow */ - if (!next_size) { - next_size = size_needed; - } + if (!next_size) { next_size = size_needed; } /* alloc */ *buf = realloc(*buf, next_size); diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 488ece81..a9764f5b 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -193,7 +193,8 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, * @return The amount of possible iteration steps to trim the input. * negative on error. */ -int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) { +int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, + size_t buf_size) { // We simply trim once data->trimmming_steps = 1; @@ -201,9 +202,12 @@ int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) data->cur_step = 0; if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) { + perror("init_trim grow"); return -1; + } + memcpy(data->trim_buf, buf, buf_size); data->trim_size_current = buf_size; diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 91564932..4211e398 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -771,7 +771,9 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, @return The rounded up power of 2 (if no overflow) or 0 on overflow. */ static inline size_t next_pow2(size_t in) { - if (in == 0 || in > (size_t)-1) return 0; /* avoid undefined behaviour under-/overflow */ + + if (in == 0 || in > (size_t)-1) + return 0; /* avoid undefined behaviour under-/overflow */ size_t out = in - 1; out |= out >> 1; out |= out >> 2; @@ -779,6 +781,7 @@ static inline size_t next_pow2(size_t in) { out |= out >> 8; out |= out >> 16; return out + 1; + } /* This function makes sure *size is > size_needed after call. @@ -804,9 +807,7 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, size_t next_size = next_pow2(size_needed); /* handle overflow */ - if (!next_size) { - next_size = size_needed; - } + if (!next_size) { next_size = size_needed; } /* alloc */ *buf = ck_realloc(*buf, next_size); diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 90d7de40..754b2190 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -213,7 +213,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { afl->stage_cur = 0; afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); - if (unlikely(afl->stage_max) < 0) FATAL("custom_init_trim error ret: %d", afl->stage_max); + if (unlikely(afl->stage_max) < 0) + FATAL("custom_init_trim error ret: %d", afl->stage_max); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, q->len); @@ -273,7 +274,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Tell the custom mutator that the trimming was unsuccessful */ afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); - if (unlikely(afl->stage_cur < 0)) FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); + if (unlikely(afl->stage_cur < 0)) + FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); if (afl->not_on_tty && afl->debug) SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, afl->stage_max); From 8b8600fdabb20c344063ead1b0ff2d105e0365be Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 13:05:26 +0100 Subject: [PATCH 35/97] types.h: silence some compiler warnings regarding redeclaration of likely/unlikely --- include/types.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/types.h b/include/types.h index bd4bd05d..ebc561f7 100644 --- a/include/types.h +++ b/include/types.h @@ -120,9 +120,13 @@ typedef int64_t s64; #define likely(_x) (_x) #define unlikely(_x) (_x) #else +#ifndef likely #define likely(_x) __builtin_expect(!!(_x), 1) +#endif +#ifndef unlikely #define unlikely(_x) __builtin_expect(!!(_x), 0) #endif +#endif #endif /* ! _HAVE_TYPES_H */ From 3c142efecfd2ec2e4dfb766819bed26b184c9671 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 13:38:49 +0100 Subject: [PATCH 36/97] qemu_mode: silence two compiler warnings --- qemu_mode/patches/afl-qemu-cpu-inl.h | 2 +- qemu_mode/patches/afl-qemu-tcg-inl.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index 9fdc23ea..3bd107d7 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -413,7 +413,7 @@ void afl_forkserver(CPUState *cpu) { void afl_persistent_loop(void) { static u32 cycle_cnt; - static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, NULL}; + static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, '\0'}; if (!afl_fork_child) return; diff --git a/qemu_mode/patches/afl-qemu-tcg-inl.h b/qemu_mode/patches/afl-qemu-tcg-inl.h index 430574e5..f7c662db 100644 --- a/qemu_mode/patches/afl-qemu-tcg-inl.h +++ b/qemu_mode/patches/afl-qemu-tcg-inl.h @@ -30,6 +30,7 @@ have a look at afl-showmap.c. */ +void afl_gen_tcg_plain_call(void *func); void afl_gen_tcg_plain_call(void *func) { From 2aa7ddf1a81baf02a1df05a987e5bfef387c25a9 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 13:51:35 +0100 Subject: [PATCH 37/97] qemu_mode: fix more compiler warnings --- qemu_mode/build_qemu_support.sh | 1 + qemu_mode/patches/__init__.py.diff | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 qemu_mode/patches/__init__.py.diff diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index bd42c58e..b27b4445 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -174,6 +174,7 @@ patch -p1 <../patches/configure.diff || exit 1 patch -p1 <../patches/tcg-runtime.diff || exit 1 patch -p1 <../patches/tcg-runtime-head.diff || exit 1 patch -p1 <../patches/translator.diff || exit 1 +patch -p1 <../patches/__init__.py.diff || exit 1 echo "[+] Patching done." diff --git a/qemu_mode/patches/__init__.py.diff b/qemu_mode/patches/__init__.py.diff new file mode 100644 index 00000000..7e189b99 --- /dev/null +++ b/qemu_mode/patches/__init__.py.diff @@ -0,0 +1,17 @@ +--- a/scripts/tracetool/__init__.py 2020-03-28 13:42:21.937700726 +0100 ++++ b/scripts/tracetool/__init__.py 2020-03-28 13:41:50.991034257 +0100 +@@ -447,12 +447,12 @@ + import tracetool + + format = str(format) +- if len(format) is 0: ++ if len(format) == 0: + raise TracetoolError("format not set") + if not tracetool.format.exists(format): + raise TracetoolError("unknown format: %s" % format) + +- if len(backends) is 0: ++ if len(backends) == 0: + raise TracetoolError("no backends specified") + for backend in backends: + if not tracetool.backend.exists(backend): From 78009d9d0700320818dc28604450f04468a9ed70 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 14:15:04 +0100 Subject: [PATCH 38/97] qemu_mode: compiler warnings, strncpy() leave one byte for terminator --- qemu_mode/build_qemu_support.sh | 1 + qemu_mode/patches/make_strncpy_safe.diff | 31 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 qemu_mode/patches/make_strncpy_safe.diff diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index b27b4445..118f6ebd 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -175,6 +175,7 @@ patch -p1 <../patches/tcg-runtime.diff || exit 1 patch -p1 <../patches/tcg-runtime-head.diff || exit 1 patch -p1 <../patches/translator.diff || exit 1 patch -p1 <../patches/__init__.py.diff || exit 1 +patch -p1 <../patches/make_strncpy_safe.diff || exit 1 echo "[+] Patching done." diff --git a/qemu_mode/patches/make_strncpy_safe.diff b/qemu_mode/patches/make_strncpy_safe.diff new file mode 100644 index 00000000..38c7d248 --- /dev/null +++ b/qemu_mode/patches/make_strncpy_safe.diff @@ -0,0 +1,31 @@ +--- a/util/qemu-sockets.c 2020-03-28 13:55:09.511029429 +0100 ++++ b/util/qemu-sockets.c 2020-03-28 14:01:12.147693937 +0100 +@@ -877,7 +877,7 @@ + + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; +- strncpy(un.sun_path, path, sizeof(un.sun_path)); ++ strncpy(un.sun_path, path, sizeof(un.sun_path) - 1); + + if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { + error_setg_errno(errp, errno, "Failed to bind socket to %s", path); +@@ -922,7 +922,7 @@ + + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; +- strncpy(un.sun_path, saddr->path, sizeof(un.sun_path)); ++ strncpy(un.sun_path, saddr->path, sizeof(un.sun_path) - 1); + + /* connect to peer */ + do { +--- a/block/sheepdog.c 2020-03-28 14:01:57.164360270 +0100 ++++ b/block/sheepdog.c 2020-03-28 14:02:52.781026597 +0100 +@@ -1236,7 +1236,7 @@ + * don't want the send_req to read uninitialized data. + */ + strncpy(buf, filename, SD_MAX_VDI_LEN); +- strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN); ++ strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN - 1); + + memset(&hdr, 0, sizeof(hdr)); + if (lock) { From 02d19dafb27e98c936453ed8defb9ad8bdadf456 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 14:23:54 +0100 Subject: [PATCH 39/97] .gitignore: add afl-ld and ld --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6bb2092a..9cb10770 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ afl-gcc afl-gcc-fast afl-g++-fast afl-gotcpu +afl-ld afl-qemu-trace afl-showmap afl-tmin @@ -39,6 +40,7 @@ afl-tmin.8 afl-whatsup.8 qemu_mode/libcompcov/compcovtest as +ld qemu_mode/qemu-* unicorn_mode/unicornafl/ unicorn_mode/samples/*/\.test-* From 2548b657d8bc9370c8fded9befb4f30b8ed3ce15 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 20:25:00 +0100 Subject: [PATCH 40/97] afl-llvm-pass.so.cc: fix compile for llvm 3.8.0 @Marc: please review --- llvm_mode/Makefile | 2 +- llvm_mode/afl-llvm-pass.so.cc | 50 +++++++++++++++++++++++++++------ llvm_mode/llvm-ngram-coverage.h | 2 +- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 2bc5fce6..6c55374b 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -268,7 +268,7 @@ endif -$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) ../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps - $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) + $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -Wno-#warnings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) ../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc ifeq "$(LLVM_LTO)" "1" diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 3b0e1fda..05904f1a 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -150,14 +150,22 @@ uint64_t PowerOf2Ceil(unsigned in) { #endif +/* #if LLVM_VERSION_STRING >= "4.0.1" */ +#if LLVM_VERSION_MAJOR >= 4 || (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) +#define AFL_HAVE_VECTOR_INTRINSICS 1 +#else +#warning this clang version does not have vector intrinsics -> no ngram instrumentation +#endif bool AFLCoverage::runOnModule(Module &M) { LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); +#ifdef AFL_HAVE_VECTOR_INTRINSICS IntegerType *IntLocTy = IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT); +#endif struct timeval tv; struct timezone tz; u32 rand_seed; @@ -198,27 +206,38 @@ bool AFLCoverage::runOnModule(Module &M) { char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO"); #endif - /* Decide previous location vector size (must be a power of two) */ + unsigned PrevLocSize; char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE"); if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE"); +#ifdef AFL_HAVE_VECTOR_INTRINSICS + /* Decide previous location vector size (must be a power of two) */ + VectorType *PrevLocTy; + if (ngram_size_str) if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 || ngram_size > MAX_NGRAM_SIZE) FATAL( - "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE)"); + "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE (%u))", + MAX_NGRAM_SIZE); - unsigned PrevLocSize; if (ngram_size == 1) ngram_size = 0; if (ngram_size) PrevLocSize = ngram_size - 1; else +#else + if (ngram_size_str) + FATAL( + "Sorry, n-gram branch coverage is not supported with llvm version %s!", + LLVM_VERSION_STRING); +#endif PrevLocSize = 1; - uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize); - VectorType *PrevLocTy; +#ifdef AFL_HAVE_VECTOR_INTRINSICS + uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize); if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize); +#endif /* Get globals for the SHM region and the previous location. Note that __afl_prev_loc is thread-local. */ @@ -228,19 +247,21 @@ bool AFLCoverage::runOnModule(Module &M) { GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); GlobalVariable *AFLPrevLoc; +#ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) -#ifdef __ANDROID__ +# ifdef __ANDROID__ AFLPrevLoc = new GlobalVariable( M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_loc"); -#else +# else AFLPrevLoc = new GlobalVariable( M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_loc", /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel, /* AddressSpace */ 0, /* IsExternallyInitialized */ false); -#endif +# endif else +#endif #ifdef __ANDROID__ AFLPrevLoc = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); @@ -250,6 +271,7 @@ bool AFLCoverage::runOnModule(Module &M) { GlobalVariable::GeneralDynamicTLSModel, 0, false); #endif +#ifdef AFL_HAVE_VECTOR_INTRINSICS /* Create the vector shuffle mask for updating the previous block history. Note that the first element of the vector will store cur_loc, so just set it to undef to allow the optimizer to do its thing. */ @@ -263,6 +285,7 @@ bool AFLCoverage::runOnModule(Module &M) { PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize)); Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle); +#endif // other constants we need ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); @@ -439,9 +462,11 @@ bool AFLCoverage::runOnModule(Module &M) { ConstantInt *CurLoc; +#ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) CurLoc = ConstantInt::get(IntLocTy, cur_loc); else +#endif CurLoc = ConstantInt::get(Int32Ty, cur_loc); /* Load prev_loc */ @@ -450,6 +475,7 @@ bool AFLCoverage::runOnModule(Module &M) { PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *PrevLocTrans; +#ifdef AFL_HAVE_VECTOR_INTRINSICS /* "For efficiency, we propose to hash the tuple as a key into the hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */ @@ -457,6 +483,7 @@ bool AFLCoverage::runOnModule(Module &M) { if (ngram_size) PrevLocTrans = IRB.CreateXorReduce(PrevLoc); else +#endif PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); /* Load SHM pointer */ @@ -465,11 +492,13 @@ bool AFLCoverage::runOnModule(Module &M) { MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *MapPtrIdx; +#ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) MapPtrIdx = IRB.CreateGEP( MapPtr, IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, CurLoc), Int32Ty)); else +#endif MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, CurLoc)); /* Update bitmap */ @@ -555,6 +584,7 @@ bool AFLCoverage::runOnModule(Module &M) { StoreInst *Store; +#ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) { Value *ShuffledPrevLoc = IRB.CreateShuffleVector( @@ -565,7 +595,9 @@ bool AFLCoverage::runOnModule(Module &M) { Store = IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } else { + } else +#endif + { Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc); diff --git a/llvm_mode/llvm-ngram-coverage.h b/llvm_mode/llvm-ngram-coverage.h index 4459bcd7..488b4fe7 100644 --- a/llvm_mode/llvm-ngram-coverage.h +++ b/llvm_mode/llvm-ngram-coverage.h @@ -12,7 +12,7 @@ typedef u64 PREV_LOC_T; #endif /* Maximum ngram size */ -#define MAX_NGRAM_SIZE 128 +#define MAX_NGRAM_SIZE 128U #endif From 699f769385b39512f3f21f0866b69eefc1f475d6 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 28 Mar 2020 23:01:12 +0100 Subject: [PATCH 41/97] review adaptions for afl-llvm-pass --- llvm_mode/Makefile | 7 ++++++- llvm_mode/afl-llvm-pass.so.cc | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 6c55374b..202dcbc6 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -201,6 +201,8 @@ else TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done endif +LLVM_MIN_4_0_1 = $(shell awk 'BEGIN { exit ARGV[1] >= ARGV[2] }' $(LLVMVER) 4.0.1; echo $$?) + all: $(TARGETS) ifeq "$(SHMAT_OK)" "1" @@ -268,7 +270,10 @@ endif -$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) ../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps - $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -Wno-#warnings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) +ifeq "$(LLVM_MIN_4_0_1)" "0" + $(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER)) +endif + $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) ../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc ifeq "$(LLVM_LTO)" "1" diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 05904f1a..8a75aa2d 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -153,8 +153,6 @@ uint64_t PowerOf2Ceil(unsigned in) { /* #if LLVM_VERSION_STRING >= "4.0.1" */ #if LLVM_VERSION_MAJOR >= 4 || (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) #define AFL_HAVE_VECTOR_INTRINSICS 1 -#else -#warning this clang version does not have vector intrinsics -> no ngram instrumentation #endif bool AFLCoverage::runOnModule(Module &M) { From ef3a13fa63c24389073a03249afacaae6bd1b814 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sun, 29 Mar 2020 09:48:01 +0200 Subject: [PATCH 42/97] llvm_mode/Makefile: replace lexical version comparison with a numerical one --- llvm_mode/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 202dcbc6..5b6fcca4 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -201,7 +201,7 @@ else TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done endif -LLVM_MIN_4_0_1 = $(shell awk 'BEGIN { exit ARGV[1] >= ARGV[2] }' $(LLVMVER) 4.0.1; echo $$?) +LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?) all: $(TARGETS) From f4844e2c0c7a85a27b4adc6764dcb938470cebba Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 00:50:04 +0200 Subject: [PATCH 43/97] added read_timed --- docs/Changelog.md | 6 ++-- include/common.h | 50 ++++++++++++++++++++++++++++++ include/types.h | 18 +++++++++-- src/afl-forkserver.c | 24 +++++---------- src/afl-fuzz-cmplog.c | 67 +++++++++++++++-------------------------- src/afl-fuzz-redqueen.c | 5 +-- src/afl-fuzz-run.c | 23 +++++--------- 7 files changed, 112 insertions(+), 81 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 198909d1..407a3324 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,12 +16,14 @@ sending a mail to . ! development and acceptance of PRs now happen only in the dev branch and only occasionally when everything is fine we PR to master - all: - - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn + - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn multiple fuzzing threads in the future or even become a library - afl basic tools now report on the environment variables picked up - more tools get environment variable usage info in the help output - force all output to stdout (some OK/SAY/WARN messages were sent to stdout, some to stderr) + - uninstrumented mode uses an internal forkserver ("fauxserver") + - reduced number of (de)allocations - afl-fuzz: - python mutator modules and custom mutator modules now use the same interface and hence the API changed @@ -38,7 +40,7 @@ sending a mail to . (https://github.com/adrianherrera/afl-ngram-pass/), activate by setting AFL_LLVM_NGRAM_SIZE - llvm_mode InsTrim mode: - - removed workaround for bug where paths were not instrumented and + - removed workaround for bug where paths were not instrumented and imported fix by author - made skipping 1 block functions an option and is disable by default, set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this diff --git a/include/common.h b/include/common.h index 8b21b55f..e8558e24 100644 --- a/include/common.h +++ b/include/common.h @@ -29,6 +29,7 @@ #include #include +#include #include #include "types.h" #include "stdbool.h" @@ -390,5 +391,54 @@ static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } +/* Wrapper for select() and read(), reading exactly len bytes. + Returns the time passed to read. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +static inline u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { + + struct timeval timeout; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + size_t read_total = 0; + size_t len_read = 0; + + while (len_read < len) { + + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + + if (!sret) { + + // printf("Timeout in sret."); + return timeout_ms + 1; + + } else if (sret < 0) { + + // perror("sret malloc"); + // TODO: catch other (errno == EINTR) than ctrl+c? + return 0; + + } + + len_read = read(fd, buf + len_read, len - len_read); + if (!len_read) { return 0; } + read_total += len_read; + + } + + s32 exec_ms = + MIN(timeout_ms, + ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); + return exec_ms > 0 ? exec_ms + : 1; // at least 1 milli must have passed (0 is an error) + +} + #endif diff --git a/include/types.h b/include/types.h index ebc561f7..da95cb39 100644 --- a/include/types.h +++ b/include/types.h @@ -58,8 +58,22 @@ typedef int32_t s32; typedef int64_t s64; #ifndef MIN -#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) -#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#define MIN(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + \ + }) +#define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) #endif /* !MIN */ #define SWAP16(_x) \ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 2dd7a9f0..01a606c3 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -164,10 +164,9 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { - struct timeval timeout; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:"); @@ -318,24 +317,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { rlen = 0; if (fsrv->exec_tmout) { - fd_set readfds; + rlen = 4; + u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen, + fsrv->exec_tmout * FORK_WAIT_MULT); - FD_ZERO(&readfds); - FD_SET(fsrv->fsrv_st_fd, &readfds); - timeout.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000); - timeout.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; - - int sret = select(fsrv->fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout); - - if (sret == 0) { + if (!time) { fsrv->child_timed_out = 1; kill(fsrv->child_pid, SIGKILL); - } else { - - rlen = read(fsrv->fsrv_st_fd, &status, 4); - } } else { diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 7c398507..08ac15c7 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -31,10 +31,9 @@ void init_cmplog_forkserver(afl_state_t *afl) { - struct timeval timeout; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; ACTF("Spinning up the cmplog fork server..."); @@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) { rlen = 0; if (afl->fsrv.exec_tmout) { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(afl->cmplog_fsrv_st_fd, &readfds); - timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000); - timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + rlen = 4; + u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; + /* Reuse readfds as exceptfds to see when the child closed the pipe */ + u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); - int sret = - select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout); + if (!time_ms) { - if (sret == 0) { + PFATAL("Error in timed read"); + } else if (time_ms > timeout_ms) { + + afl->fsrv.child_timed_out = 1; kill(afl->cmplog_fsrv_pid, SIGKILL); - - } else { - rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); } @@ -213,6 +210,11 @@ void init_cmplog_forkserver(afl_state_t *afl) { /* If we have a four-byte "hello" message from the server, we're all set. Otherwise, try to figure out what went wrong. */ + if (afl->fsrv.child_timed_out) + FATAL( + "Timeout while initializing cmplog fork server (adjusting -t may " + "help)"); + if (rlen == 4) { OKF("All right - fork server is up."); @@ -220,11 +222,6 @@ void init_cmplog_forkserver(afl_state_t *afl) { } - if (afl->fsrv.child_timed_out) - FATAL( - "Timeout while initializing cmplog fork server (adjusting -t may " - "help)"); - if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); @@ -379,16 +376,12 @@ void init_cmplog_forkserver(afl_state_t *afl) { u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { - struct timeval it; - int status = 0; - int sret; - u64 exec_ms; + int status = 0; + u64 exec_ms; u32 tb4; s32 res; - fd_set readfds; - afl->fsrv.child_timed_out = 0; /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we @@ -423,18 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ + u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); - it.tv_sec = (timeout / 1000); - it.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&readfds); - FD_SET(afl->cmplog_fsrv_st_fd, &readfds); - it.tv_sec = ((timeout) / 1000); - it.tv_usec = ((timeout) % 1000) * 1000; - - sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it); - - if (sret == 0) { + if (time_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ @@ -442,9 +426,12 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { kill(afl->cmplog_child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; + /* After killing the child, the forkserver should tell us */ + if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) time_ms = 0; + } - if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) { + if (!time_ms) { // Something went wrong. if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST @@ -467,12 +454,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0; - exec_ms = (u64)timeout - (it.tv_sec * 1000 + it.tv_usec / 1000); if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms; - it.tv_sec = 0; - it.tv_usec = 0; - ++afl->total_execs; /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index b069fa77..4acc204b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -529,9 +529,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, if (!afl->shm.cmp_map->headers[k].hits) continue; if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) - afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); + afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); else - afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); + afl->stage_max += + MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 90cb2ed5..f58e1a33 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -33,13 +33,10 @@ u8 run_target(afl_state_t *afl, u32 timeout) { s32 res; - int sret; + u32 time_ms; - fd_set readfds; - - struct timeval it; - int status = 0; - u32 tb4; + int status = 0; + u32 tb4; afl->fsrv.child_timed_out = 0; @@ -70,26 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) { if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - /* use select to monitor the forkserver for timeouts. */ + time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); - FD_ZERO(&readfds); - FD_SET(afl->fsrv.fsrv_st_fd, &readfds); - it.tv_sec = ((timeout) / 1000); - it.tv_usec = ((timeout) % 1000) * 1000; - - sret = select(afl->fsrv.fsrv_st_fd + 1, &readfds, NULL, NULL, &it); - - if (sret == 0) { + if (time_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ kill(afl->fsrv.child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; + if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) time_ms = 0; } - if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) { + if (!time_ms) { if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST From 28e5a8031ce84bfe4baab9504c141bc79f470031 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 00:50:32 +0200 Subject: [PATCH 44/97] code cleanup --- llvm_mode/afl-llvm-pass.so.cc | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 8a75aa2d..5fe98d8b 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -151,7 +151,8 @@ uint64_t PowerOf2Ceil(unsigned in) { #endif /* #if LLVM_VERSION_STRING >= "4.0.1" */ -#if LLVM_VERSION_MAJOR >= 4 || (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) +#if LLVM_VERSION_MAJOR >= 4 || \ + (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) #define AFL_HAVE_VECTOR_INTRINSICS 1 #endif bool AFLCoverage::runOnModule(Module &M) { @@ -217,7 +218,8 @@ bool AFLCoverage::runOnModule(Module &M) { if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 || ngram_size > MAX_NGRAM_SIZE) FATAL( - "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE (%u))", + "Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE " + "(%u))", MAX_NGRAM_SIZE); if (ngram_size == 1) ngram_size = 0; @@ -233,7 +235,7 @@ bool AFLCoverage::runOnModule(Module &M) { PrevLocSize = 1; #ifdef AFL_HAVE_VECTOR_INTRINSICS - uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize); + uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize); if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize); #endif @@ -247,26 +249,26 @@ bool AFLCoverage::runOnModule(Module &M) { #ifdef AFL_HAVE_VECTOR_INTRINSICS if (ngram_size) -# ifdef __ANDROID__ +#ifdef __ANDROID__ AFLPrevLoc = new GlobalVariable( M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_loc"); -# else +#else AFLPrevLoc = new GlobalVariable( M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, /* Initializer */ nullptr, "__afl_prev_loc", /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel, /* AddressSpace */ 0, /* IsExternallyInitialized */ false); -# endif +#endif else #endif #ifdef __ANDROID__ AFLPrevLoc = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); #else - AFLPrevLoc = new GlobalVariable( - M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0, - GlobalVariable::GeneralDynamicTLSModel, 0, false); + AFLPrevLoc = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0, + GlobalVariable::GeneralDynamicTLSModel, 0, false); #endif #ifdef AFL_HAVE_VECTOR_INTRINSICS @@ -594,6 +596,7 @@ bool AFLCoverage::runOnModule(Module &M) { Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); } else + #endif { From 1279c935e27a6cc90d12111d4220e04f317e3916 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 30 Mar 2020 11:33:42 +0200 Subject: [PATCH 45/97] regec dict additions --- dictionaries/regexp.dict | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dictionaries/regexp.dict b/dictionaries/regexp.dict index 2f29357e..0ca0a720 100644 --- a/dictionaries/regexp.dict +++ b/dictionaries/regexp.dict @@ -601,3 +601,12 @@ "[\x8f]" "[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\x92\xa9-\xf4\x8f\xbf\xbf]" "[\x92\xa9-\xf4\x8f\xbf\xbf]" +"\\1\\2(b\\1\\2))\\2)\\1" +"\\1\\2(a(?:\\1\\2))\\2)\\1" +"?:\\1" +"\\1(b\\1\\2))\\2)\\1" +"\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1" +"foo(?=bar)bar)baz" +"fo(?o(?o(?o(?=bar)baz" +"foo(?=bar)baz" +"foo(?=bar)bar)az" From 209aa25d27fa6f0cfe8f9713d338b68a11f968e2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:01:29 +0200 Subject: [PATCH 46/97] added unittest for unit_maybe_alloc --- Makefile | 19 ++-- include/alloc-inl.h | 31 +++++++ test/unittests/unit_maybe_alloc.c | 140 ++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 test/unittests/unit_maybe_alloc.c diff --git a/Makefile b/Makefile index fed33d57..2e4a6570 100644 --- a/Makefile +++ b/Makefile @@ -3,13 +3,13 @@ # ----------------------------- # # Originally written by Michal Zalewski -# +# # Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved. -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: -# +# # http://www.apache.org/licenses/LICENSE-2.0 # @@ -311,13 +311,20 @@ afl-gotcpu: src/afl-gotcpu.c $(COMM_HDR) | test_x86 document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86 $(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS) +test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES) + $(CC) $(CFLAGS) $(CFLAGS_FLTO) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o +unit_maybe_alloc: test/unittests/unit_maybe_alloc.o + $(CC) $(CFLAGS) -lcmocka -Wl,--wrap=exit -Wl,--wrap=printf $(LDFLAGS) test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc + ./test/unittests/unit_maybe_alloc + +unit: unit_maybe_alloc code-format: ./.custom-format.py -i src/*.c ./.custom-format.py -i include/*.h - ./.custom-format.py -i libdislocator/*.c - ./.custom-format.py -i libtokencap/*.c + ./.custom-format.py -i libdislocator/*.c + ./.custom-format.py -i libtokencap/*.c ./.custom-format.py -i llvm_mode/*.c ./.custom-format.py -i llvm_mode/*.h ./.custom-format.py -i llvm_mode/*.cc @@ -364,7 +371,7 @@ all_done: test_build .NOTPARALLEL: clean clean: - rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 + rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM -$(MAKE) -C llvm_mode clean -$(MAKE) -C gcc_plugin clean diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 4211e398..47a16bb8 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -784,6 +784,35 @@ static inline size_t next_pow2(size_t in) { } +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will return NULL and free *buf if size_needed is <1 or realloc failed. + @return For convenience, this function returns *buf. + */ +static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { + + /* No need to realloc */ + if (likely(size_needed && *size >= size_needed)) return *buf; + + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + + /* handle overflow and zero size_needed */ + if (!next_size) { next_size = size_needed; } + + /* alloc */ + *buf = realloc(*buf, next_size); + *size = *buf ? next_size : 0; + + return *buf; + +} + /* This function makes sure *size is > size_needed after call. It will realloc *buf otherwise. *size will grow exponentially as per: @@ -817,6 +846,8 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, } + + /* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, size_t *size2) { diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c new file mode 100644 index 00000000..93f10889 --- /dev/null +++ b/test/unittests/unit_maybe_alloc.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include + +extern void mock_assert(const int result, const char* const expression, + const char * const file, const int line); +#undef assert +#define assert(expression) \ + mock_assert((int)(expression), #expression, __FILE__, __LINE__); +#include "alloc-inl.h" + +/* remap exit -> assert, then use cmocka's mock_assert + (compile with `--wrap=exit`) */ +extern void exit(int status); +extern void __real_exit(int status); +void __wrap_exit(int status) { + assert(0); +} + +/* ignore all printfs */ +extern int printf(const char *format, ...); +extern int __real_printf(const char *format, ...); +int __wrap_printf(const char *format, ...) { + return 1; +} + +#define BUF_PARAMS (void **)&buf, &size + +static int setup(void **state) { + + return 0; + +} + +static void test_null_allocs(void **state) { + + void *buf = NULL; + size_t size = 0; + void *ptr = ck_maybe_grow(BUF_PARAMS, 100); + assert_true(buf == ptr); + assert_true(size >= 100); + ck_free(ptr); + +} + +static void test_nonpow2_size(void **state) { + + char *buf = ck_alloc(150); + size_t size = 150; + buf[140] = '5'; + char *ptr = ck_maybe_grow(BUF_PARAMS, 160); + assert_ptr_equal(buf, ptr); + assert_true(size >= 160); + assert_true(buf[140] == '5'); + ck_free(ptr); + +} + +static void test_zero_size() { + + char *buf = NULL; + size_t size = 0; + //assert_non_null(maybe_grow(BUF_PARAMS, 0)); + free(buf); + buf = NULL; + size = 0; + + char *ptr = ck_maybe_grow(BUF_PARAMS, 100); + assert_non_null(ptr); + assert_ptr_equal(buf, ptr); + assert_true(size >= 100); + + expect_assert_failure(ck_maybe_grow(BUF_PARAMS, 0)); + +} + +static void test_unchanged_size(void **state) { + + void *buf = ck_alloc(100); + size_t size = 100; + void *buf_before = buf; + void *buf_after = ck_maybe_grow(BUF_PARAMS, 100); + assert_ptr_equal(buf, buf_after); + assert_ptr_equal(buf_after, buf_before); + ck_free(buf); + +} + +static void test_grow_multiple(void **state) { + + char *buf = NULL; + size_t size = 0; + + char *ptr = ck_maybe_grow(BUF_PARAMS, 100); + assert_ptr_equal(ptr, buf); + assert_true(size >= 100); + assert_int_equal(size, next_pow2(size)); + buf[50] = '5'; + + ptr = (char *)ck_maybe_grow(BUF_PARAMS, 1000); + assert_ptr_equal(ptr, buf); + assert_true(size >= 100); + assert_int_equal(size, next_pow2(size)); + buf[500] = '5'; + + ptr = (char *)ck_maybe_grow(BUF_PARAMS, 10000); + assert_ptr_equal(ptr, buf); + assert_true(size >= 10000); + assert_int_equal(size, next_pow2(size)); + buf[5000] = '5'; + + assert_int_equal(buf[50], '5'); + assert_int_equal(buf[500], '5'); + assert_int_equal(buf[5000], '5'); + + ck_free(buf); + +} + +static int teardown(void **state) { + + return 0; + +} + +int main(int argc, char **argv) { + + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_null_allocs), + cmocka_unit_test(test_nonpow2_size), + cmocka_unit_test(test_zero_size), + cmocka_unit_test(test_unchanged_size), + cmocka_unit_test(test_grow_multiple), + }; + + return cmocka_run_group_tests (tests, setup, teardown); + +} \ No newline at end of file From 50a195fe5955a7b6711bfd975c17d2e6bd1a82f2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:07:25 +0200 Subject: [PATCH 47/97] code format --- include/alloc-inl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 47a16bb8..89889cc5 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -846,8 +846,6 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, } - - /* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, size_t *size2) { From 6bdd7a16098051105fb574b8fd372da6e8eb5525 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:08:07 +0200 Subject: [PATCH 48/97] added untitest to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9cb10770..2687f959 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ unicorn_mode/unicornafl/ unicorn_mode/samples/*/\.test-* unicorn_mode/samples/*/output/ core\.* +test/unittests/unit_maybe_alloc From c697a003d1f6026c0e98cd1fcdfac5aca6af4e35 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:45:13 +0200 Subject: [PATCH 49/97] merged dev --- docs/custom_mutators.md | 7 ++++--- examples/README.md | 8 +++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 2163b2d5..ef97b8d3 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -30,7 +30,8 @@ C/C++: void afl_custom_init(void *afl, unsigned int seed); size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf, size_t add_buf_size, size_t max_size); -size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, uint8_t** out_buf); +size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, + uint8_t* out_buf, size_t out_buf_size); uint32_t afl_custom_init_trim(uint8_t* buf, size_t buf_size); void afl_custom_trim(uint8_t** out_buf, size_t* out_buf_size); uint32_t afl_custom_post_trim(uint8_t success); @@ -111,7 +112,7 @@ def queue_new_entry(filename_new_queue, filename_orig_queue): - `queue_new_entry` (optional): - This methods is called after adding a new test case to the queue. + This methods is called after adding a new test case to the queue. ### Trimming Support @@ -167,7 +168,7 @@ a fallback to the builtin default trimming routine. Optionally, the following environment variables are supported: - `AFL_CUSTOM_MUTATOR_ONLY` - + Disable all other mutation stages. This can prevent broken testcases (those that your Python module can't work with anymore) to fill up your queue. Best combined with a custom trimming routine (see below) because diff --git a/examples/README.md b/examples/README.md index 37fae1a0..6c09caeb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,8 +3,6 @@ Here's a quick overview of the stuff you can find in this directory: - custom_mutstors - An example custom mutator - - - python_mutators - Python mutators examples - argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed (e.g., to test setuid programs). @@ -15,8 +13,8 @@ Here's a quick overview of the stuff you can find in this directory: - bash_shellshock - a simple hack used to find a bunch of post-Shellshock bugs in bash. - - canvas_harness - a test harness used to find browser bugs with a - corpus generated using simple image parsing + - canvas_harness - a test harness used to find browser bugs with a + corpus generated using simple image parsing binaries & afl-fuzz. - clang_asm_normalize - a script that makes it easy to instrument @@ -34,7 +32,7 @@ Here's a quick overview of the stuff you can find in this directory: mode to speed up certain fuzzing jobs. - post_library - an example of how to build postprocessors for AFL. - + - socket_fuzzing - a LD_PRELOAD library 'redirects' a socket to stdin for fuzzing access with afl++ From c6248317174ef8fd61360148c8ef95ed7c806a7e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:46:05 +0200 Subject: [PATCH 50/97] upstream changes --- llvm_mode/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 5b6fcca4..006d115d 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -329,7 +329,7 @@ install: all install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) ifndef AFL_TRACE_PC if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi - if [ -f ../afl-clang-lto -a -f ../afl-ld ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 ../afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi + if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi else if [ -f ../afl-clang-fast -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi endif From ff14dfc0fc099cf68a9a9b4168b601be45d03e1c Mon Sep 17 00:00:00 2001 From: h1994st Date: Fri, 27 Mar 2020 02:03:20 -0400 Subject: [PATCH 51/97] Add a test case for the custom mutator - Update the Makefile in examples/custom_mutators - Add a test program for testing the custom mutator - Update test.sh for testing the custom mutator - [TODO] Update the result checking criterias of the custom mutator in test.sh --- examples/custom_mutators/Makefile | 7 +- test/test-custom-mutator.c | 20 +++++ test/test.sh | 128 +++++++++++++++++++++++------- 3 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 test/test-custom-mutator.c diff --git a/examples/custom_mutators/Makefile b/examples/custom_mutators/Makefile index a83e87fe..463cefb1 100644 --- a/examples/custom_mutators/Makefile +++ b/examples/custom_mutators/Makefile @@ -1,2 +1,7 @@ -all: +all: libexamplemutator.so + +libexamplemutator.so: $(CC) $(CFLAGS) -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so + +clean: + rm -rf libexamplemutator.so diff --git a/test/test-custom-mutator.c b/test/test-custom-mutator.c new file mode 100644 index 00000000..b44c3634 --- /dev/null +++ b/test/test-custom-mutator.c @@ -0,0 +1,20 @@ +/** + * Reference: https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/blob/master/4_libprotobuf_aflpp_custom_mutator/vuln.c + */ + +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + char str[100]={ }; + read(0, str, 100); + int *ptr = NULL; + if( str[0] == 'P') { + *ptr = 123; + } + return 0; +} diff --git a/test/test.sh b/test/test.sh index ec4e71d0..725ae9e4 100755 --- a/test/test.sh +++ b/test/test.sh @@ -60,8 +60,8 @@ unset AFL_QEMU_PERSISTENT_GPR unset AFL_QEMU_PERSISTENT_RET unset AFL_QEMU_PERSISTENT_HOOK unset AFL_QEMU_PERSISTENT_CNT -unset AFL_POST_LIBRARY -unset AFL_CUSTOM_MUTATOR_LIBRARY + +export unset AFL_CUSTOM_MUTATOR_LIBRARY=unset AFL_POST_LIBRARY unset AFL_PYTHON_MODULE unset AFL_PRELOAD unset LD_PRELOAD @@ -73,7 +73,7 @@ export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1: # on OpenBSD we need to work with llvm from /usr/local/bin test -e /usr/local/bin/opt && { export PATH=/usr/local/bin:${PATH} -} +} # on MacOS X we prefer afl-clang over afl-gcc, because # afl-gcc does not work there test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && { @@ -142,11 +142,11 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 } rm -f test-compcov.harden - } || { + } || { $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed" CODE=1 } - # now we want to be sure that afl-fuzz is working + # now we want to be sure that afl-fuzz is working # make sure core_pattern is set to core on linux (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && { $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET" @@ -210,13 +210,13 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc unset AFL_QUIET } rm -f test-instr.plain - } || { + } || { $ECHO "$YELLOW[-] afl is not compiled, cannot test" INCOMPLETE=1 } -} || { +} || { $ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc" -} +} $ECHO "$BLUE[*] Testing: llvm_mode, afl-showmap, afl-fuzz, afl-cmin and afl-tmin" test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { @@ -248,7 +248,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 } } - } || { + } || { $ECHO "$RED[!] llvm_mode instrumentation failed" CODE=1 } @@ -265,11 +265,11 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 } rm -f test-compcov.harden - } || { + } || { $ECHO "$RED[!] llvm_mode hardened mode compilation failed" CODE=1 } - # now we want to be sure that afl-fuzz is working + # now we want to be sure that afl-fuzz is working (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && { $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET" true @@ -373,7 +373,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { $ECHO "$RED[!] llvm_mode whitelist feature failed" CODE=1 } - } || { + } || { $ECHO "$RED[!] llvm_mode whitelist feature compilation failed" CODE=1 } @@ -426,7 +426,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { CODE=1 } } - } || { + } || { $ECHO "$RED[!] llvm_mode LTO instrumentation failed" CODE=1 } @@ -447,7 +447,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { # $ECHO "$RED[!] llvm_mode LTO whitelist feature failed" # CODE=1 # } -# } || { +# } || { # $ECHO "$RED[!] llvm_mode LTO whitelist feature compilation failed" # CODE=1 # } @@ -483,7 +483,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] gcc_plugin instrumentation should be different on different input but is not" CODE=1 - } || { + } || { $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly" TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && { @@ -516,7 +516,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { $ECHO "$RED[!] gcc_plugin hardened mode compilation failed" CODE=1 } - # now we want to be sure that afl-fuzz is working + # now we want to be sure that afl-fuzz is working (test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && { $ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET" true @@ -552,11 +552,11 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && { test -e test-compcov && { echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && { $ECHO "$GREEN[+] gcc_plugin whitelist feature works correctly" - } || { + } || { $ECHO "$RED[!] gcc_plugin whitelist feature failed" CODE=1 } - } || { + } || { $ECHO "$RED[!] gcc_plugin whitelist feature compilation failed" CODE=1 } @@ -585,7 +585,7 @@ test -e ../libtokencap.so && { AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1 grep -q BUGMENOT token.out > /dev/null 2>&1 && { $ECHO "$GREEN[+] libtokencap did successfully capture tokens" - } || { + } || { $ECHO "$RED[!] libtokencap did not capture tokens" CODE=1 } @@ -604,7 +604,7 @@ test -e ../libdislocator.so && { $ECHO "$RED[!] libdislocator did not detect the memory corruption" CODE=1 } || { - $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption" + $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption" } rm -f test.out core test-compcov.core core.test-compcov } || { @@ -700,7 +700,7 @@ test -e ../afl-qemu-trace && { test -e ../libcompcov.so && { $ECHO "$GREY[*] running afl-fuzz for qemu_mode compcov, this will take approx 10 seconds" { - export AFL_PRELOAD=../libcompcov.so + export AFL_PRELOAD=../libcompcov.so export AFL_COMPCOV_LEVEL=2 ../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1 unset AFL_PRELOAD @@ -720,10 +720,10 @@ test -e ../afl-qemu-trace && { INCOMPLETE=1 } rm -f errors - } || { + } || { $ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode compcov" } - + test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && { $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds" { @@ -757,9 +757,9 @@ test -e ../afl-qemu-trace && { exit 1 } rm -rf in out errors - } || { + } || { $ECHO "$YELLOW[-] not an intel or arm platform, cannot test persistent qemu_mode" - } + } test -e ../qemu_mode/unsigaction/unsigaction32.so && { ${AFL_CC} -o test-unsigaction32 -m32 test-unsigaction.c >> errors 2>&1 && { @@ -824,7 +824,7 @@ test -e ../afl-qemu-trace && { $ECHO "$RED[!] gcc compilation of test targets failed - what is going on??" CODE=1 } - + rm -f test-instr test-compcov } || { $ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test" @@ -887,12 +887,86 @@ test -d ../unicorn_mode/unicornafl && { $ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??" CODE=1 } - + } || { $ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test" INCOMPLETE=1 } +$ECHO "$BLUE[*] Testing: custom mutator" +unset AFL_CC # Line 474 sets AFL_CC to "gcc". We reset it to use the default compiler +CUSTOM_MUTATOR_PATH=../examples/custom_mutators +test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c && { + # Compile the vulnerable program + ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c + # Compile the custom mutator + make -C ../examples/custom_mutators libexamplemutator.so + test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && { + # Create input directory + mkdir -p in + echo 00000 > in/in + + # Run afl-fuzz w/ the C mutator + $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" + { + export AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator + unset AFL_CUSTOM_MUTATOR_LIBRARY + } >>errors 2>&1 + + # Check results + test -n "$( ls out/queue/id:000001* 2>/dev/null )" && { # TODO: update here + $ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator" + } || { + echo CUT------------------------------------------------------------------CUT + cat errors + echo CUT------------------------------------------------------------------CUT + $ECHO "$RED[!] afl-fuzz is not working correctly with the C mutator" + CODE=1 + } + + # Clean + rm -rf out errors + + # Run afl-fuzz w/ the Python mutator + $ECHO "$GREY[*] running afl-fuzz for the Python mutator, this will take approx 10 seconds" + { + export PYTHONPATH=${CUSTOM_MUTATOR_PATH} + export AFL_PYTHON_MODULE=example + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator + unset PYTHONPATH + unset AFL_PYTHON_MODULE + } >>errors 2>&1 + + # Check results + test -n "$( ls out/queue/id:000001* 2>/dev/null )" && { # TODO: update here + $ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator" + } || { + echo CUT------------------------------------------------------------------CUT + cat errors + echo CUT------------------------------------------------------------------CUT + $ECHO "$RED[!] afl-fuzz is not working correctly with the Python mutator" + CODE=1 + } + + # Clean + rm -rf in out errors + rm -rf ${CUSTOM_MUTATOR_PATH}/__pycache__/ + } || { + ls . + ls ${CUSTOM_MUTATOR_PATH} + $ECHO "$RED[!] cannot compile the test program or the custom mutator" + CODE=1 + } + + make -C ../examples/custom_mutators clean > /dev/null 2>&1 + rm -f test-custom-mutator +} || { + $ECHO "$YELLOW[-] no custom mutators in $CUSTOM_MUTATOR_PATH, cannot test" + INCOMPLETE=1 +} +unset CUSTOM_MUTATOR_PATH + $ECHO "$GREY[*] all test cases completed.$RESET" test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed" test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed" From 87621b6345a2e140d60b116edf3592c67ede2113 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:46:50 +0200 Subject: [PATCH 52/97] rebase --- src/afl-fuzz-mutators.c | 4 ++-- test/test.sh | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 754b2190..1a5528a2 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -193,8 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* Initialize the custom mutator */ if (afl->mutator->afl_custom_init) - afl->mutator->data = - afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); + afl->mutator->data = afl->mutator->afl_custom_init( + afl, rand_below(afl, 0xFFFFFFFF)); } diff --git a/test/test.sh b/test/test.sh index 725ae9e4..0d3c7199 100755 --- a/test/test.sh +++ b/test/test.sh @@ -895,12 +895,12 @@ test -d ../unicorn_mode/unicornafl && { $ECHO "$BLUE[*] Testing: custom mutator" unset AFL_CC # Line 474 sets AFL_CC to "gcc". We reset it to use the default compiler -CUSTOM_MUTATOR_PATH=../examples/custom_mutators +CUSTOM_MUTATOR_PATH=$( realpath ../examples/custom_mutators ) test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c && { # Compile the vulnerable program - ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c + ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 # Compile the custom mutator - make -C ../examples/custom_mutators libexamplemutator.so + make -C ../examples/custom_mutators libexamplemutator.so > /dev/null 2>&1 test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && { # Create input directory mkdir -p in From 048beb752db51252f1374e1b91ee73fd9174acb6 Mon Sep 17 00:00:00 2001 From: h1994st Date: Fri, 27 Mar 2020 21:03:06 -0400 Subject: [PATCH 53/97] Fix typo --- examples/custom_mutators/example.py | 3 +-- test/test.sh | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/custom_mutators/example.py b/examples/custom_mutators/example.py index 6bacfa05..6b58188e 100644 --- a/examples/custom_mutators/example.py +++ b/examples/custom_mutators/example.py @@ -164,11 +164,10 @@ def fuzz(buf, add_buf, max_size): # ''' # Called after adding a new test case to the queue # -# @type filename_new_queue: str +# @type filename_new_queue: str # @param filename_new_queue: File name of the new queue entry # # @type filename_orig_queue: str # @param filename_orig_queue: File name of the original queue entry # ''' # pass - diff --git a/test/test.sh b/test/test.sh index 0d3c7199..11c4be25 100755 --- a/test/test.sh +++ b/test/test.sh @@ -60,8 +60,8 @@ unset AFL_QEMU_PERSISTENT_GPR unset AFL_QEMU_PERSISTENT_RET unset AFL_QEMU_PERSISTENT_HOOK unset AFL_QEMU_PERSISTENT_CNT - -export unset AFL_CUSTOM_MUTATOR_LIBRARY=unset AFL_POST_LIBRARY +unset AFL_POST_LIBRARY +unset AFL_CUSTOM_MUTATOR_LIBRARY unset AFL_PYTHON_MODULE unset AFL_PRELOAD unset LD_PRELOAD From fbd5bd8f37c9285d5201c969587067586c9109bc Mon Sep 17 00:00:00 2001 From: h1994st Date: Sat, 28 Mar 2020 00:52:29 -0400 Subject: [PATCH 54/97] Fix invalid memory access bug in `afl_custom_pre_save` of example.c --- examples/custom_mutators/example.c | 16 +++++++++------- src/afl-fuzz-python.c | 3 ++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index a9764f5b..7d827029 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -157,15 +157,17 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, } - *out_buf = data->pre_save_buf; + uint8_t *pre_save_buf = data->pre_save_buf; - memcpy(*out_buf + 5, buf, buf_size); + memcpy(pre_save_buf + 5, buf, buf_size); size_t out_buf_size = buf_size + 5; - *out_buf[0] = 'A'; - *out_buf[1] = 'F'; - *out_buf[2] = 'L'; - *out_buf[3] = '+'; - *out_buf[4] = '+'; + pre_save_buf[0] = 'A'; + pre_save_buf[1] = 'F'; + pre_save_buf[2] = 'L'; + pre_save_buf[3] = '+'; + pre_save_buf[4] = '+'; + + *out_buf = pre_save_buf; return out_buf_size; diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 91e5b084..01503d2c 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -133,8 +133,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { if (py_module != NULL) { u8 py_notrim = 0, py_idx; + /* init, required */ py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init"); - py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit"); py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz"); py_functions[PY_FUNC_PRE_SAVE] = PyObject_GetAttrString(py_module, "pre_save"); @@ -151,6 +151,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { PyObject_GetAttrString(py_module, "queue_get"); py_functions[PY_FUNC_QUEUE_NEW_ENTRY] = PyObject_GetAttrString(py_module, "queue_new_entry"); + py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit"); for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) { From 45561d552e8612fbae91641a43a7db6597af9dba Mon Sep 17 00:00:00 2001 From: h1994st Date: Sun, 29 Mar 2020 01:06:28 -0400 Subject: [PATCH 55/97] example.py: add deinit() --- examples/custom_mutators/example.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/custom_mutators/example.py b/examples/custom_mutators/example.py index 6b58188e..7919d3d3 100644 --- a/examples/custom_mutators/example.py +++ b/examples/custom_mutators/example.py @@ -27,6 +27,10 @@ def init(seed): random.seed(seed) +def deinit(): + pass + + def fuzz(buf, add_buf, max_size): ''' Called per fuzzing iteration. From 567b3985ab680ac9188c96cd3820653c344c9755 Mon Sep 17 00:00:00 2001 From: h1994st Date: Sun, 29 Mar 2020 01:07:29 -0400 Subject: [PATCH 56/97] python mutator: fix nullptr for python mutator data --- include/afl-fuzz.h | 3 --- src/afl-fuzz-python.c | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index a265c1a3..fcbc09e5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -566,9 +566,6 @@ typedef struct afl_state { /* Custom mutators */ struct custom_mutator *mutator; -#ifdef USE_PYTHON - struct custom_mutator *py_mutator; -#endif /* cmplog forkserver ids */ s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd; diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 01503d2c..12c3a09d 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -303,6 +303,7 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) { py_mutator_t *py_mutator; py_mutator = init_py_module(afl, module_name); + afl->mutator->data = py_mutator; if (!py_mutator) { FATAL("Failed to load python mutator."); } PyObject **py_functions = py_mutator->py_functions; From 6c14415664228a3b5ab245af9b37fb6672619b49 Mon Sep 17 00:00:00 2001 From: h1994st Date: Sun, 29 Mar 2020 01:22:44 -0400 Subject: [PATCH 57/97] test.sh: "trusty-amd64" does not work well with "realpath". Use "readlink -f" for Ubuntu instead. --- examples/custom_mutators/example.py | 12 ++++++++++-- test/test.sh | 16 ++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/examples/custom_mutators/example.py b/examples/custom_mutators/example.py index 7919d3d3..9e95eed6 100644 --- a/examples/custom_mutators/example.py +++ b/examples/custom_mutators/example.py @@ -17,6 +17,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. import random +COMMANDS = [ + b"GET", + b"PUT", + b"DEL", +] + + def init(seed): ''' Called once when AFLFuzz starts up. Used to seed our RNG. @@ -48,8 +55,9 @@ def fuzz(buf, add_buf, max_size): @rtype: bytearray @return: A new bytearray containing the mutated data ''' - ret = bytearray(buf) - # Do something interesting with ret + ret = bytearray(100) + + ret[:3] = random.choice(COMMANDS) return ret diff --git a/test/test.sh b/test/test.sh index 11c4be25..c9ce3489 100755 --- a/test/test.sh +++ b/test/test.sh @@ -894,9 +894,13 @@ test -d ../unicorn_mode/unicornafl && { } $ECHO "$BLUE[*] Testing: custom mutator" -unset AFL_CC # Line 474 sets AFL_CC to "gcc". We reset it to use the default compiler -CUSTOM_MUTATOR_PATH=$( realpath ../examples/custom_mutators ) -test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c && { +unset AFL_CC # Test case "gcc_plugin" sets AFL_CC to "gcc". We reset it to use the default compiler +test `uname -s` = 'Darwin' && { + CUSTOM_MUTATOR_PATH=$( realpath ../examples/custom_mutators ) +} || { + CUSTOM_MUTATOR_PATH=$( readlink -f ../examples/custom_mutators ) +} +test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && { # Compile the vulnerable program ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 # Compile the custom mutator @@ -904,7 +908,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && { # Create input directory mkdir -p in - echo 00000 > in/in + echo "00000" > in/in # Run afl-fuzz w/ the C mutator $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" @@ -915,7 +919,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS } >>errors 2>&1 # Check results - test -n "$( ls out/queue/id:000001* 2>/dev/null )" && { # TODO: update here + test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && { # TODO: update here $ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator" } || { echo CUT------------------------------------------------------------------CUT @@ -939,7 +943,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS } >>errors 2>&1 # Check results - test -n "$( ls out/queue/id:000001* 2>/dev/null )" && { # TODO: update here + test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && { # TODO: update here $ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator" } || { echo CUT------------------------------------------------------------------CUT From d9b18ec8530e09f4bcbdb4e1f51bb0e83b4182c8 Mon Sep 17 00:00:00 2001 From: h1994st Date: Mon, 30 Mar 2020 05:21:01 -0400 Subject: [PATCH 58/97] Fix heap allocation bug - Reason: `afl->out_size` is not consistent with the actual allocation of `afl->out_buf`. The deleted line in `src/afl-fuzz-one.c` may change `afl->out_size`, but `afl->out_buf` is not changed --- examples/custom_mutators/example.c | 12 ++++++------ src/afl-fuzz-one.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 7d827029..ec47104d 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -159,13 +159,13 @@ size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t *pre_save_buf = data->pre_save_buf; - memcpy(pre_save_buf + 5, buf, buf_size); + memcpy(pre_save_buf, buf, buf_size); size_t out_buf_size = buf_size + 5; - pre_save_buf[0] = 'A'; - pre_save_buf[1] = 'F'; - pre_save_buf[2] = 'L'; - pre_save_buf[3] = '+'; - pre_save_buf[4] = '+'; + pre_save_buf[buf_size + 0] = 'A'; + pre_save_buf[buf_size + 1] = 'F'; + pre_save_buf[buf_size + 2] = 'L'; + pre_save_buf[buf_size + 3] = '+'; + pre_save_buf[buf_size + 4] = '+'; *out_buf = pre_save_buf; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b1bbad0a..29dd73ad 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1621,8 +1621,6 @@ custom_mutator_stage: if (unlikely(!mutated_buf)) FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size); - if (mutated_size > len) afl->out_size = mutated_size; - if (mutated_size > 0) { if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) { @@ -1650,6 +1648,8 @@ custom_mutator_stage: } out_buf = ck_maybe_grow(BUF_PARAMS(out), len); + // ??? (h1994st): this line may be not necessary, as we do not modify the + // content of "out_buf". memcpy(out_buf, in_buf, len); } From 57a0134b0cd5a2b9fe6d5ce2d6591b34894635c1 Mon Sep 17 00:00:00 2001 From: h1994st Date: Mon, 30 Mar 2020 05:28:30 -0400 Subject: [PATCH 59/97] test.sh: redirect command line output --- test/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.sh b/test/test.sh index c9ce3489..25aaad58 100755 --- a/test/test.sh +++ b/test/test.sh @@ -914,7 +914,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" { export AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 unset AFL_CUSTOM_MUTATOR_LIBRARY } >>errors 2>&1 @@ -937,7 +937,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS { export PYTHONPATH=${CUSTOM_MUTATOR_PATH} export AFL_PYTHON_MODULE=example - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator + ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 unset PYTHONPATH unset AFL_PYTHON_MODULE } >>errors 2>&1 From e2a3de71ca8c9ab36d43fac2752e4a9ccf31e814 Mon Sep 17 00:00:00 2001 From: h1994st Date: Mon, 30 Mar 2020 06:01:01 -0400 Subject: [PATCH 60/97] afl-fuzz-one.c: minor update --- src/afl-fuzz-one.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 29dd73ad..c61c9084 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1647,10 +1647,10 @@ custom_mutator_stage: } + /* `afl->out_buf` is actually not changed in the loop. Since `ck_maybe_grow` + is cheap, we still keep the following line but remove `memcpy`. */ out_buf = ck_maybe_grow(BUF_PARAMS(out), len); - // ??? (h1994st): this line may be not necessary, as we do not modify the - // content of "out_buf". - memcpy(out_buf, in_buf, len); + // memcpy(out_buf, in_buf, len); } From 1f257c5875d8b99d774ec9f473c06f73862d0688 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 16:38:51 +0200 Subject: [PATCH 61/97] fixed example --- examples/custom_mutators/example.c | 33 +++++++++++------------------- src/afl-fuzz-one.c | 6 ++---- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index ec47104d..c8200b26 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -142,34 +142,25 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) { - if (data->pre_save_size < buf_size + 5) { + uint8_t *pre_save_buf = maybe_grow(BUF_PARAMS(data, pre_save), buf_size + 5); + if (!pre_save_buf) { - data->pre_save_buf = maybe_grow(BUF_PARAMS(data, pre_save), buf_size + 5); - if (!data->pre_save_buf) { - - perror("custom mutator realloc failed."); - *out_buf = NULL; - return 0; - - } - - data->pre_save_size = buf_size + 5; + perror("custom mutator realloc failed."); + *out_buf = NULL; + return 0; } - uint8_t *pre_save_buf = data->pre_save_buf; - - memcpy(pre_save_buf, buf, buf_size); - size_t out_buf_size = buf_size + 5; - pre_save_buf[buf_size + 0] = 'A'; - pre_save_buf[buf_size + 1] = 'F'; - pre_save_buf[buf_size + 2] = 'L'; - pre_save_buf[buf_size + 3] = '+'; - pre_save_buf[buf_size + 4] = '+'; + memcpy(pre_save_buf + 5, buf, buf_size); + pre_save_buf[0] = 'A'; + pre_save_buf[1] = 'F'; + pre_save_buf[2] = 'L'; + pre_save_buf[3] = '+'; + pre_save_buf[4] = '+'; *out_buf = pre_save_buf; - return out_buf_size; + return buf_size + 5; } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c61c9084..2e49e19b 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1647,10 +1647,8 @@ custom_mutator_stage: } - /* `afl->out_buf` is actually not changed in the loop. Since `ck_maybe_grow` - is cheap, we still keep the following line but remove `memcpy`. */ - out_buf = ck_maybe_grow(BUF_PARAMS(out), len); - // memcpy(out_buf, in_buf, len); + /* `(afl->)out_buf` may have been changed by the call to custom_fuzz */ + memcpy(out_buf, in_buf, len); } From caebc9347fefc454316a66f18096c63f7ce3a17a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 30 Mar 2020 17:45:17 +0200 Subject: [PATCH 62/97] added unit target to make help and README --- Makefile | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 2e4a6570..f10aadc9 100644 --- a/Makefile +++ b/Makefile @@ -206,6 +206,7 @@ help: @echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well" @echo "code-format: format the code, do this before you commit and send a PR please!" @echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem" + @echo "unit: perform unit tests (based on cmocka)" @echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations" @echo "help: shows these build options :-)" @echo "==========================================" diff --git a/README.md b/README.md index 827a7aec..e1ca5949 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ These build targets exist: * clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well * code-format: format the code, do this before you commit and send a PR please! * tests: runs test cases to ensure that all features are still working as they should +* unit: perform unit tests (based on cmocka) * help: shows these build options [Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the From 3fcb3e2ed3918c652f2db1ad088c7848b170bf89 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 18:20:20 +0200 Subject: [PATCH 63/97] fixed testcase --- test/test-custom-mutator.c | 7 +++---- test/test.sh | 4 +--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/test/test-custom-mutator.c b/test/test-custom-mutator.c index b44c3634..83baafab 100644 --- a/test/test-custom-mutator.c +++ b/test/test-custom-mutator.c @@ -10,11 +10,10 @@ int main(int argc, char *argv[]) { - char str[100]={ }; + char str[100]; read(0, str, 100); - int *ptr = NULL; - if( str[0] == 'P') { - *ptr = 123; + if( str[6] == 'A') { + abort(); } return 0; } diff --git a/test/test.sh b/test/test.sh index 25aaad58..3e1b6c43 100755 --- a/test/test.sh +++ b/test/test.sh @@ -913,9 +913,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS # Run afl-fuzz w/ the C mutator $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" { - export AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so - ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 - unset AFL_CUSTOM_MUTATOR_LIBRARY + AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 } >>errors 2>&1 # Check results From 6544014ced58c3d13123e693d644cf6b86b378ee Mon Sep 17 00:00:00 2001 From: Shengtuo Hu Date: Mon, 30 Mar 2020 12:21:03 -0400 Subject: [PATCH 64/97] Add test cases for the custom mutator (#276) * Minor update * Fix the soft link of `afl-clang-fast++` * Add a test case for the custom mutator - Update the Makefile in examples/custom_mutators - Add a test program for testing the custom mutator - Update test.sh for testing the custom mutator - [TODO] Update the result checking criterias of the custom mutator in test.sh * Fix nullptr in the custom mutator * Fix typo * Fix invalid memory access bug in `afl_custom_pre_save` of example.c * example.py: add deinit() * python mutator: fix nullptr for python mutator data * test.sh: "trusty-amd64" does not work well with "realpath". Use "readlink -f" for Ubuntu instead. * Fix heap allocation bug - Reason: `afl->out_size` is not consistent with the actual allocation of `afl->out_buf`. The deleted line in `src/afl-fuzz-one.c` may change `afl->out_size`, but `afl->out_buf` is not changed * test.sh: redirect command line output * afl-fuzz-one.c: minor update Co-authored-by: Dominik Maier From a58382d3ff774c795d5cf7c583cd1e162c4155a1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 18:37:16 +0200 Subject: [PATCH 65/97] added unittests to test.sh --- .travis.yml | 4 ++-- test/test.sh | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2c8c8bea..92c8f5a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,8 +41,8 @@ before_install: # export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE} - echo Testing on $NAME - if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi - - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils ; fi - - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils ; fi + - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils cmocka ; fi + - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils cmocka ; fi script: - gcc -v diff --git a/test/test.sh b/test/test.sh index 3e1b6c43..de730c15 100755 --- a/test/test.sh +++ b/test/test.sh @@ -969,6 +969,10 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS } unset CUSTOM_MUTATOR_PATH +$ECHO "$BLUE[*] Execution cmocka Unit-Tests $GREY" +unset AFL_CC +make -C .. unit || "$CODE" = "1" + $ECHO "$GREY[*] all test cases completed.$RESET" test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed" test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed" From 8f5fb47082e1e4051eaa96c8b89fb1d6dbe70a8a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 18:38:39 +0200 Subject: [PATCH 66/97] code format --- src/afl-fuzz-mutators.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 1a5528a2..754b2190 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -193,8 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* Initialize the custom mutator */ if (afl->mutator->afl_custom_init) - afl->mutator->data = afl->mutator->afl_custom_init( - afl, rand_below(afl, 0xFFFFFFFF)); + afl->mutator->data = + afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); } From ac48b58184393b65ef351a69d04e1c6bce052a99 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 18:46:12 +0200 Subject: [PATCH 67/97] mutator docs --- docs/custom_mutators.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index ef97b8d3..ebf08c40 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -27,19 +27,15 @@ performed with the custom mutator. C/C++: ```c -void afl_custom_init(void *afl, unsigned int seed); -size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf, - size_t add_buf_size, size_t max_size); -size_t afl_custom_write_to_testcase(uint8_t* buf, size_t buf_size, - uint8_t* out_buf, size_t out_buf_size); -uint32_t afl_custom_init_trim(uint8_t* buf, size_t buf_size); -void afl_custom_trim(uint8_t** out_buf, size_t* out_buf_size); -uint32_t afl_custom_post_trim(uint8_t success); -size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size); -uint8_t afl_custom_havoc_mutation_probability(void); -uint8_t afl_custom_queue_get(const uint8_t* filename); -void afl_custom_queue_new_entry(const uint8_t* filename_new_queue, - const uint8_t* filename_orig_queue); +void *afl_custom_init(afl_t *afl, unsigned int seed); +size_t afl_custom_fuzz(void *data, uint8_t *buf, size_t buf_size, u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, size_t max_size); +size_t afl_custom_pre_save(void *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf); +int32_t afl_custom_init_trim(void *data, uint8_t *buf, size_t buf_size); +size_t afl_custom_trim(void *data, uint8_t **out_buf); +int32_t afl_custom_post_trim(void *data, int success) { +size_t afl_custom_havoc_mutation(void *data, u8 *buf, size_t buf_size, u8 **out_buf, size_t max_size); +uint8_t afl_custom_havoc_mutation_probability(void *data); +uint8_t afl_custom_queue_get(void *data, const uint8_t *filename); void afl_custom_queue_new_entry(void *data, const uint8_t *filename_new_queue, const uint8_t *filename_orig_queue); void afl_custom_deinit(void *data); ``` From 9110097e111b7043e3a76234dfe624dbc2b717ee Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 18:55:54 +0200 Subject: [PATCH 68/97] fix ubuntu cmocka pkgname --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 92c8f5a2..e6c6affa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,8 +41,8 @@ before_install: # export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE} - echo Testing on $NAME - if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi - - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils cmocka ; fi - - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils cmocka ; fi + - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi + - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi script: - gcc -v From 64e9f1f3a2db60281dde303c4b9371b5efbb534f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 23:53:10 +0200 Subject: [PATCH 69/97] tiny fixes --- docs/custom_mutators.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index ebf08c40..49ce761e 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -74,9 +74,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue): ### Custom Mutation -- `init` (optional): +- `init`: - This method is called when AFL++ starts up and is used to seed RNG. + This method is called when AFL++ starts up and is used to seed RNG and set up buffers and state. - `queue_get` (optional): @@ -142,7 +142,7 @@ trimmed input. Here's a quick API description: This method is called for each trimming operation. It doesn't have any arguments because we already have the initial buffer from `init_trim` and we - can memorize the current state in global variables. This can also save + can memorize the current state in the data variables. This can also save reparsing steps for each iteration. It should return the trimmed input buffer, where the returned data must not exceed the initial input data in length. Returning anything that is larger than the original data (passed to @@ -156,6 +156,8 @@ trimmed input. Here's a quick API description: In any case, this method must return the next trim iteration index (from 0 to the maximum amount of steps you returned in `init_trim`). +`deinit` the last method to be called, deinitializing the state. + Omitting any of three methods will cause the trimming to be disabled and trigger a fallback to the builtin default trimming routine. From a249dadfb09a45f6ba0279f81c62d48477389a73 Mon Sep 17 00:00:00 2001 From: Dhiraj Mishra Date: Mon, 30 Mar 2020 23:00:22 +0400 Subject: [PATCH 70/97] Update regexp.dict --- dictionaries/regexp.dict | 360 +-------------------------------------- 1 file changed, 2 insertions(+), 358 deletions(-) diff --git a/dictionaries/regexp.dict b/dictionaries/regexp.dict index 0ca0a720..8ac3357b 100644 --- a/dictionaries/regexp.dict +++ b/dictionaries/regexp.dict @@ -1,6 +1,6 @@ # -# AFL dictionary for regex -# -------------------------- +# AFL dictionary for JS regex +# --------------------------- # # Contains various regular expressions. # @@ -238,362 +238,6 @@ "\\p{Nd}" "\\P{Any}" "\\p{Changes_When_NFKC_Casefolded}" -"L~" -"P{scx=Greek}??" -"Q~" -"R??" -"R!??oo(E=?ar)baz-" -"Sc?Sc{?{?" -"U~" -"V~" -"W~" -"Xdtc" -"X~" -"X?" -"[-123],}" -"[-????]+,}" -"[00011],}" -"[011],}" -"[0],}" -"[1111],}" -"[111],}" -"[118],}" -"[11],}" -"[11a],}" -"[[]{}()%^# ],}" -"[]" -"[],}" -"[]{}()%^# ,}" -"[^123],}" -"[a-b-c],}" -"[a-zA-Z0-9],}" -"[b" -"[bfoo(?!bar)baz" -"[c!],}" -"[c1],}" -"[cA],}" -"[cZ],}" -"[c_],}" -"[ca],}" -"[cz],}" -"[c~],}" -"[c~]w" -"[d-d],}" -"[d-z],}" -"[u???[11<([c?]?:u??)dccc]" -"[ud808udf45-ud809udccc],}" -"[x" -"[x],}" -"[xdz],}" -"[xyz],}" -"[x?" -"[x?n4n4" -"[x??19?" -"[z-d],}" -"[~?" -"[?????" -"[?" -"[???],}" -"[????-????],}" -"[????" -"]" -"],}" -"]QrC[w~]Qr" -"]}" -"]~" -"^?000???????????????????????????x60?" -"^12(a(?:1(b12))2)1dyb?9" -"^xi!q" -"^xxx$,}" -"abc" -"abc60,0}?{?" -"aic" -"b~" -"c" -"c!,}" -"c,}" -"cA,}" -"c_,}" -"cjcJcicIckcK,}" -"c~" -"c~,}" -"d" -"d?" -"d??" -"d(?:ab[]?9}" -"dpN?(?.)?" -"duu{123a?" -"d{1,9" -"d~" -"e" -"e~" -"e?}" -"f~" -"g~" -"h~" -"i~" -"j~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xx?~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxb~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxc~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxd~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxe~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxf~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxg~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxh~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxi~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxj~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxk~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxl~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxm~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxn~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxo~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxp~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxr~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxs~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxt~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxu~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxv~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxw~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxx~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxy~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxz~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xx?~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxn~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxo~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxp~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxq~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxr~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxs~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxt~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxu~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxv~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxw~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxx~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxy~" -"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxz~" -"k?@a(?=bbb.~" -"k?@a(?=bbbb~" -"k?@a(?=bbbc~" -"k?@a(?=bbbd~" -"k?@a(?=bbbe~" -"k?@a(?=bbbf~" -"k?@a(?=bbbg~" -"k?@a(?=bbbh~" -"k?@a(?=bbbi~" -"k?@a(?=bbbj~" -"k?@a(?=bbbk~" -"k?@a(?=bbbl~" -"k?@a(?=bbbm~" -"k?@a(?=bbbn~" -"k?@a(?=bbbo~" -"k?@a(?=bbbp~" -"k?@a(?=bbbq~" -"k?@a(?=bbbr~" -"k?@a(?=bbbs~" -"k?@a(?=bbbt~" -"k?@a(?=bbbu~" -"k?@a(?=bbbv~" -"k?@a(?=bbbw~" -"k?@a(?=bbbx~" -"k?@a(?=bbby~" -"k?@a(?=bbbz~" -"k?@a(?=by?bC?:!k??????????????b~" -"k?@a(?=by?bC?:!k??????????????c~" -"k?@a(?=by?bC?:!k??????????????d~" -"k?@a(?=by?bC?:!k??????????????e~" -"k?@a(?=by?bC?:!k??????????????f~" -"k?@a(?=by?bC?:!k??????????????g~" -"k?@a(?=by?bC?:!k??????????????h~" -"k?@a(?=by?bC?:!k??????????????i~" -"k?@a(?=by?bC?:!k??????????????j~" -"k?@a(?=by?bC?:!k??????????????k~" -"k?@a(?=by?bC?:!k??????????????l~" -"k?@a(?=by?bC?:!k??????????????m~" -"k?@a(?=by?bC?:!k??????????????n~" -"k?@a(?=by?bC?:!k??????????????o~" -"k?@a(?=by?bC?:!k??????????????p~" -"k?@a(?=by?bC?:!k??????????????q~" -"k?@a(?=by?bC?:!k??????????????r~" -"k?@a(?=by?bC?:!k??????????????s~" -"k?@a(?=by?bC?:!k??????????????t~" -"k?@a(?=by?bC?:!k??????????????u~" -"k?@a(?=by?bC?:!k??????????????v~" -"k?@a(?=by?bC?:!k??????????????w~" -"k?@a(?=by?bC?:!k??????????????x~" -"k?@a(?=by?bC?:!k??????????????y~" -"k?@a(?=by?bC?:!k??????????????z~" -"k?@a(?=by?bC?:!k???????????????~" -"k?@a(?~" -"k?@a(b~" -"k?@a(c~" -"k?@a(d~" -"k?@a(e~" -"k?@a(f~" -"k?@a(g~" -"k?@a(h~" -"k?@a(i~" -"k?@a(j~" -"k?@a(k~" -"k?@a(l~" -"k?@a(m~" -"k?@a(n~" -"k?@a(o~" -"k?@a(p~" -"k?@a(q~" -"k?@a(r~" -"k?@a(s~" -"k?@a(t~" -"k?@a(u~" -"k?@a(v~" -"k?@a(w~" -"k?@a(x~" -"k?@a(y~" -"k?@a(z~" -"k0X@ab~" -"k0X@ac~" -"k0X@ad~" -"k0X@ae~" -"k0X@af~" -"k0X@ag~" -"k0X@ah~" -"k0X@ai~" -"k0X@aj~" -"k0X@ak~" -"k0X@al~" -"k0X@am~" -"k0X@an~" -"k0X@ao~" -"k0X@ap~" -"k0X@aq~" -"k0X@ar~" -"k0X@as~" -"k0X@at~" -"k0X@au~" -"k0X@av~" -"k0X@aw~" -"k0X@ax~" -"k0X@ay~" -"k0X@az~" -"k0X@a?~" -"k~" -"l~" -"m~" -"n~" -"o~" -"p~" -"q,}" -"q~" -"r~" -"r?[c~]" -"s~" -"t~" -"u0034,}" -"u003z,}" -"u0060,}" -"ud808udf45*,}" -"u~" -"v~" -"w" -"w~" -"x3z,}" -"x60,}" -"xyz?9" -"x~" -"y~" -"z~" -"{" -"{??" -"{ ,,?" -"{-" -"{0,d?????!" -"{12345}pu{234:P}?" -"{1?5" -"{@" -"{M,??" -"{M,P{scx=Greek}???sn" -"{M,??" -"{M,??" -"{M,?M,??" -"{O" -"{r~" -"{s~" -"{t~" -"{u~" -"{v~" -"{w~" -"{x~" -"{y~" -"{z~" -"{}" -"{}~" -"{??@" -"{?~" -"},}" -"}}" -"}}}}}?}!}}}}}}}}}}}}}}}}}?},}" -"}~" -"}?w~???" -"~~" -"?!~" -"?$" -"?*?9?nnRnnn?" -"?.~" -"?123222222??" -"?:??" -"?R" -"?b~" -"?c~" -"?d~" -"?d???" -"?e~" -"?f~" -"?g~" -"?h~" -"?i~" -"?j~" -"?k~" -"?l~" -"?m~" -"?n~" -"?o~" -"?p~" -"?q~" -"?r~" -"?s~" -"?t~" -"?u~" -"?v~" -"?v~?v" -"?w~" -"?x~" -"?y~" -"?z~" -"?}" -"??~" -"?????????dadi(?!bbb" -"??~" -"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~>>>>>>>>>>>>>>>>>>" -"?f??123222222??" -"?fP{gc=Decimal_Number}" -"?f2jq?oo@ooooh??" -"?[???],}f?" -"?[???],}nbbc2jocom" -"?[]" -"?[],}?" -"?[],}f?" -"?[]f?" -"?[]{}()%^#" -"?[^123],}f?" -"?[^123]nbbc2jocom" -"?[a-b-c],}f?" -"?[a-b-c]nbbc2jocom" -"?[a-zA-Z0-9],}f?" -"?[a-zA-Z0-9],}jocom" -"?[a-zA-Z0-9]c2jocom" -"?[bfoo(?!bar)bazcom" -"?[bfoo(?!bar)bazf?" "(?:a?)??" "a?)"xyz{93}" "{93}" From daa09a5fbb301083a701fba1ee8feb7d9fdb4c2b Mon Sep 17 00:00:00 2001 From: Dhiraj Mishra Date: Mon, 30 Mar 2020 23:01:24 +0400 Subject: [PATCH 71/97] Update regexp.dict --- dictionaries/regexp.dict | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dictionaries/regexp.dict b/dictionaries/regexp.dict index 8ac3357b..4e2d7a0f 100644 --- a/dictionaries/regexp.dict +++ b/dictionaries/regexp.dict @@ -1,6 +1,6 @@ # -# AFL dictionary for JS regex -# --------------------------- +# AFL dictionary for regex +# -------------------------- # # Contains various regular expressions. # From d3130ace303a5bb20714f0de933e7eb3204c38fe Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 02:41:11 +0200 Subject: [PATCH 72/97] enabled fortify source --- Makefile | 2 +- include/afl-prealloc.h | 5 ++--- include/common.h | 2 +- include/list.h | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index f10aadc9..6d8f857a 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ ifneq "$(shell uname -m)" "x86_64" endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -override CFLAGS += -Wall -g -Wno-pointer-sign -I include/ \ +override CFLAGS += -Wall -g -Wno-pointer-sign -D_FORTIFY_SOURCE=2 -I include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index ab86f0d7..66e6aadf 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -44,9 +44,8 @@ typedef enum prealloc_status { /* Adds the entry used for prealloc bookkeeping to this struct */ -#define PREALLOCABLE \ - ; \ - pre_status_t pre_status; /* prealloc status of this instance */ +/* prealloc status of this instance */ +#define PREALLOCABLE pre_status_t pre_status /* allocate an element of type *el_ptr, to this variable. Uses (and reuses) the given prealloc_buf before hitting libc's malloc. diff --git a/include/common.h b/include/common.h index e8558e24..db102777 100644 --- a/include/common.h +++ b/include/common.h @@ -426,7 +426,7 @@ static inline u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { } - len_read = read(fd, buf + len_read, len - len_read); + len_read = read(fd, ((u8 *)buf) + len_read, len - len_read); if (!len_read) { return 0; } read_total += len_read; diff --git a/include/list.h b/include/list.h index 1190931f..25ee8282 100644 --- a/include/list.h +++ b/include/list.h @@ -34,8 +34,8 @@ #include "debug.h" #include "afl-prealloc.h" -#define LIST_PREALLOC_SIZE \ - (64) /* How many elements to allocate before malloc is needed */ +/* How many elements to allocate before malloc is needed */ +#define LIST_PREALLOC_SIZE (64) typedef struct list_element { From 9b63fc758e9a296eabaa2f452f2d72e204db1240 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 03:22:46 +0200 Subject: [PATCH 73/97] dropped make switches --- Makefile | 10 +- include/afl-fuzz.h | 2 +- include/common.h | 363 ++--------------------------------------- include/list.h | 8 +- src/afl-common.c | 390 +++++++++++++++++++++++++++++++++++++++++++++ src/afl-showmap.c | 20 --- 6 files changed, 411 insertions(+), 382 deletions(-) diff --git a/Makefile b/Makefile index 6d8f857a..cbef4b7c 100644 --- a/Makefile +++ b/Makefile @@ -65,9 +65,9 @@ ifneq "$(shell uname -m)" "x86_64" endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -override CFLAGS += -Wall -g -Wno-pointer-sign -D_FORTIFY_SOURCE=2 -I include/ \ - -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ - -DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon +override CFLAGS += -Wall -g -Wno-pointer-sign -D_FORTIFY_SOURCE=2 \ + -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \ + -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) @@ -304,8 +304,8 @@ afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS) -afl-gotcpu: src/afl-gotcpu.c $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS) +afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) # document all mutations and only do one run (use with only one input file!) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index fcbc09e5..e750d7c9 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -967,7 +967,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) { /* Find first power of two greater or equal to val (assuming val under 2^63). */ -static u64 next_p2(u64 val) { +static inline u64 next_p2(u64 val) { u64 ret = 1; while (val > ret) diff --git a/include/common.h b/include/common.h index db102777..db92e32d 100644 --- a/include/common.h +++ b/include/common.h @@ -50,395 +50,54 @@ char * get_afl_env(char *env); /* Get unix time in milliseconds */ -static u64 get_cur_time(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); - -} +u64 get_cur_time(void); /* Get unix time in microseconds */ -static u64 get_cur_time_us(void) { - - struct timeval tv; - struct timezone tz; - - gettimeofday(&tv, &tz); - - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - -} +u64 get_cur_time_us(void); /* Describe integer. The buf should be at least 6 bytes to fit all ints we randomly see. Will return buf for convenience. */ -static u8 *stringify_int(u8 *buf, size_t len, u64 val) { -\ -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ - do { \ - \ - if (val < (_divisor) * (_limit_mult)) { \ - \ - snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \ - return buf; \ - \ - } \ - \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strncpy(buf, "infty", len); - buf[len - 1] = '\0'; - - return buf; - -} +u8 *stringify_int(u8 *buf, size_t len, u64 val); /* Describe float. Similar as int. */ -static u8 *stringify_float(u8 *buf, size_t len, double val) { - - if (val < 99.995) { - - snprintf(buf, len, "%0.02f", val); - - } else if (val < 999.95) { - - snprintf(buf, len, "%0.01f", val); - - } else { - - stringify_int(buf, len, (u64)val); - - } - - return buf; - -} +u8 *stringify_float(u8 *buf, size_t len, double val); /* Describe integer as memory size. */ -static u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strncpy(buf, "infty", len - 1); - buf[len - 1] = '\0'; - - return buf; - -} +u8 *stringify_mem_size(u8 *buf, size_t len, u64 val); /* Describe time delta as string. Returns a pointer to buf for convenience. */ -static u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { - - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - if (!event_ms) { - - snprintf(buf, len, "none seen yet"); - - } else { - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - stringify_int(val_buf, sizeof(val_buf), t_d); - snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, - t_s); - - } - - return buf; - -} +u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms); /* Unsafe Describe integer. The buf sizes are not checked. This is unsafe but fast. Will return buf for convenience. */ -static u8 *u_stringify_int(u8 *buf, u64 val) { -\ -#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ - do { \ - \ - if (val < (_divisor) * (_limit_mult)) { \ - \ - sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \ - return buf; \ - \ - } \ - \ - } while (0) - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1000, 99.95, "%0.01fk", double); - - /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); - - /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); - - /* 100G - 999G */ - CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); - - /* 100T+ */ - strcpy(buf, "infty"); - - return buf; - -} +u8 *u_stringify_int(u8 *buf, u64 val); /* Unsafe describe float. Similar as unsafe int. */ -static u8 *u_stringify_float(u8 *buf, double val) { - - if (val < 99.995) { - - sprintf(buf, "%0.02f", val); - - } else if (val < 999.95) { - - sprintf(buf, "%0.01f", val); - - } else { - - return u_stringify_int(buf, (u64)val); - - } - - return buf; - -} +u8 *u_stringify_float(u8 *buf, double val); /* Unsafe describe integer as memory size. */ -static u8 *u_stringify_mem_size(u8 *buf, u64 val) { - - /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); - - /* 10.0k - 99.9k */ - CHK_FORMAT(1024, 99.95, "%0.01f kB", double); - - /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); - - /* 1.00M - 9.99M */ - CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); - - /* 10.0M - 99.9M */ - CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); - - /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); - - /* 1.00G - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); - - /* 10.0G - 99.9G */ - CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); - - /* 100G - 999G */ - CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); - - /* 1.00T - 9.99G */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); - - /* 10.0T - 99.9T */ - CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); - -#undef CHK_FORMAT - - /* 100T+ */ - strcpy(buf, "infty"); - - return buf; - -} +u8 *u_stringify_mem_size(u8 *buf, u64 val); /* Unsafe describe time delta as string. Returns a pointer to buf for convenience. */ -static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { - - u64 delta; - s32 t_d, t_h, t_m, t_s; - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - if (!event_ms) { - - sprintf(buf, "none seen yet"); - - } else { - - delta = cur_ms - event_ms; - - t_d = delta / 1000 / 60 / 60 / 24; - t_h = (delta / 1000 / 60 / 60) % 24; - t_m = (delta / 1000 / 60) % 60; - t_s = (delta / 1000) % 60; - - u_stringify_int(val_buf, t_d); - sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s); - - } - - return buf; - -} +u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); /* Wrapper for select() and read(), reading exactly len bytes. Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -static inline u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { - - struct timeval timeout; - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; - - size_t read_total = 0; - size_t len_read = 0; - - while (len_read < len) { - - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - - if (!sret) { - - // printf("Timeout in sret."); - return timeout_ms + 1; - - } else if (sret < 0) { - - // perror("sret malloc"); - // TODO: catch other (errno == EINTR) than ctrl+c? - return 0; - - } - - len_read = read(fd, ((u8 *)buf) + len_read, len - len_read); - if (!len_read) { return 0; } - read_total += len_read; - - } - - s32 exec_ms = - MIN(timeout_ms, - ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); - return exec_ms > 0 ? exec_ms - : 1; // at least 1 milli must have passed (0 is an error) - -} +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms); #endif - diff --git a/include/list.h b/include/list.h index 25ee8282..c67b24b2 100644 --- a/include/list.h +++ b/include/list.h @@ -60,13 +60,13 @@ static inline element_t *get_head(list_t *list) { } -static void list_free_el(list_t *list, element_t *el) { +static inline void list_free_el(list_t *list, element_t *el) { PRE_FREE(el, list->element_prealloc_count); } -static void list_append(list_t *list, void *el) { +static inline void list_append(list_t *list, void *el) { element_t *head = get_head(list); if (!head->next) { @@ -143,7 +143,7 @@ static void list_append(list_t *list, void *el) { /* remove an item from the list */ -static void list_remove(list_t *list, void *remove_me) { +static inline void list_remove(list_t *list, void *remove_me) { LIST_FOREACH(list, void, { @@ -165,7 +165,7 @@ static void list_remove(list_t *list, void *remove_me) { /* Returns true if el is in list */ -static bool list_contains(list_t *list, void *contains_me) { +static inline bool list_contains(list_t *list, void *contains_me) { LIST_FOREACH(list, void, { diff --git a/src/afl-common.c b/src/afl-common.c index e10de6b3..785d7c4c 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -30,6 +30,7 @@ #include "debug.h" #include "alloc-inl.h" #include "envs.h" +#include "common.h" /* Detect @@ in args. */ #ifndef __glibc__ @@ -393,3 +394,392 @@ char *get_afl_env(char *env) { } +u64 get_cur_time(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); + +} + +/* Get unix time in microseconds */ + +u64 get_cur_time_us(void) { + + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv, &tz); + + return (tv.tv_sec * 1000000ULL) + tv.tv_usec; + +} + +/* Describe integer. The buf should be + at least 6 bytes to fit all ints we randomly see. + Will return buf for convenience. */ + +u8 *stringify_int(u8 *buf, size_t len, u64 val) { + +#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ + do { \ + \ + if (val < (_divisor) * (_limit_mult)) { \ + \ + snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \ + return buf; \ + \ + } \ + \ + } while (0) + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1000, 99.95, "%0.01fk", double); + + /* 100k - 999k */ + CHK_FORMAT(1000, 1000, "%lluk", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); + + /* 100M - 999M */ + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); + + /* 100G - 999G */ + CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); + + /* 100T+ */ + strncpy(buf, "infty", len); + buf[len - 1] = '\0'; + + return buf; + +} + +/* Describe float. Similar as int. */ + +u8 *stringify_float(u8 *buf, size_t len, double val) { + + if (val < 99.995) { + + snprintf(buf, len, "%0.02f", val); + + } else if (val < 999.95) { + + snprintf(buf, len, "%0.01f", val); + + } else { + + stringify_int(buf, len, (u64)val); + + } + + return buf; + +} + +/* Describe integer as memory size. */ + +u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu B", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1024, 99.95, "%0.01f kB", double); + + /* 100k - 999k */ + CHK_FORMAT(1024, 1000, "%llu kB", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); + + /* 100M - 999M */ + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); + + /* 100G - 999G */ + CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); + +#undef CHK_FORMAT + + /* 100T+ */ + strncpy(buf, "infty", len - 1); + buf[len - 1] = '\0'; + + return buf; + +} + +/* Describe time delta as string. + Returns a pointer to buf for convenience. */ + +u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { + + u64 delta; + s32 t_d, t_h, t_m, t_s; + u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + + if (!event_ms) { + + snprintf(buf, len, "none seen yet"); + + } else { + + delta = cur_ms - event_ms; + + t_d = delta / 1000 / 60 / 60 / 24; + t_h = (delta / 1000 / 60 / 60) % 24; + t_m = (delta / 1000 / 60) % 60; + t_s = (delta / 1000) % 60; + + stringify_int(val_buf, sizeof(val_buf), t_d); + snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, + t_s); + + } + + return buf; + +} + +/* Unsafe Describe integer. The buf sizes are not checked. + This is unsafe but fast. + Will return buf for convenience. */ + +u8 *u_stringify_int(u8 *buf, u64 val) { + +#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ + do { \ + \ + if (val < (_divisor) * (_limit_mult)) { \ + \ + sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \ + return buf; \ + \ + } \ + \ + } while (0) + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1000, 99.95, "%0.01fk", double); + + /* 100k - 999k */ + CHK_FORMAT(1000, 1000, "%lluk", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); + + /* 100M - 999M */ + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double); + + /* 100G - 999G */ + CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double); + + /* 100T+ */ + strcpy(buf, "infty"); + + return buf; + +} + +/* Unsafe describe float. Similar as unsafe int. */ + +u8 *u_stringify_float(u8 *buf, double val) { + + if (val < 99.995) { + + sprintf(buf, "%0.02f", val); + + } else if (val < 999.95) { + + sprintf(buf, "%0.01f", val); + + } else { + + return u_stringify_int(buf, (u64)val); + + } + + return buf; + +} + +/* Unsafe describe integer as memory size. */ + +u8 *u_stringify_mem_size(u8 *buf, u64 val) { + + /* 0-9999 */ + CHK_FORMAT(1, 10000, "%llu B", u64); + + /* 10.0k - 99.9k */ + CHK_FORMAT(1024, 99.95, "%0.01f kB", double); + + /* 100k - 999k */ + CHK_FORMAT(1024, 1000, "%llu kB", u64); + + /* 1.00M - 9.99M */ + CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); + + /* 10.0M - 99.9M */ + CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); + + /* 100M - 999M */ + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + + /* 1.00G - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); + + /* 10.0G - 99.9G */ + CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double); + + /* 100G - 999G */ + CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64); + + /* 1.00T - 9.99G */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double); + + /* 10.0T - 99.9T */ + CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double); + +#undef CHK_FORMAT + + /* 100T+ */ + strcpy(buf, "infty"); + + return buf; + +} + +/* Unsafe describe time delta as string. + Returns a pointer to buf for convenience. */ + +u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { + + u64 delta; + s32 t_d, t_h, t_m, t_s; + u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + + if (!event_ms) { + + sprintf(buf, "none seen yet"); + + } else { + + delta = cur_ms - event_ms; + + t_d = delta / 1000 / 60 / 60 / 24; + t_h = (delta / 1000 / 60 / 60) % 24; + t_m = (delta / 1000 / 60) % 60; + t_s = (delta / 1000) % 60; + + u_stringify_int(val_buf, t_d); + sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s); + + } + + return buf; + +} + +/* Wrapper for select() and read(), reading exactly len bytes. + Returns the time passed to read. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { + + struct timeval timeout; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + size_t read_total = 0; + size_t len_read = 0; + + while (len_read < len) { + + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + + if (!sret) { + + // printf("Timeout in sret."); + return timeout_ms + 1; + + } else if (sret < 0) { + + // perror("sret malloc"); + // TODO: catch other (errno == EINTR) than ctrl+c? + return 0; + + } + + len_read = read(fd, ((u8 *)buf) + len_read, len - len_read); + if (!len_read) { return 0; } + read_total += len_read; + + } + + s32 exec_ms = + MIN(timeout_ms, + ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); + return exec_ms > 0 ? exec_ms + : 1; // at least 1 milli must have passed (0 is an error) + +} diff --git a/src/afl-showmap.c b/src/afl-showmap.c index caacefe4..eaab5c31 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -224,26 +224,6 @@ static u32 write_results(afl_forkserver_t *fsrv) { } -/* Write output file. */ - -static s32 write_to_file(u8 *path, u8 *mem, u32 len) { - - s32 ret; - - unlink(path); /* Ignore errors */ - - ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); - - if (ret < 0) PFATAL("Unable to create '%s'", path); - - ck_write(ret, mem, len, path); - - lseek(ret, 0, SEEK_SET); - - return ret; - -} - /* Write modified data to file for testing. If use_stdin is clear, the old file is unlinked and a new one is created. Otherwise, out_fd is rewound and truncated. */ From 3914aec72f0c0e9eb57a5b2b026e1522763d6bad Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 03:41:51 +0200 Subject: [PATCH 74/97] src doku is now markdown --- Makefile | 2 +- docs/Changelog.md | 5 ++-- include/common.h | 1 + qbdi_mode/build.sh | 2 +- src/README.md | 24 ++++++++++++++++++++ src/README.src | 22 ------------------ src/afl-common.c | 5 ++-- src/{afl-fuzz-globals.c => afl-fuzz-state.c} | 0 8 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 src/README.md delete mode 100644 src/README.src rename src/{afl-fuzz-globals.c => afl-fuzz-state.c} (100%) diff --git a/Makefile b/Makefile index cbef4b7c..b45cf9d3 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) override CFLAGS += -Wall -g -Wno-pointer-sign -D_FORTIFY_SOURCE=2 \ - -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \ + -I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \ -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) diff --git a/docs/Changelog.md b/docs/Changelog.md index 407a3324..1b97812c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -23,7 +23,8 @@ sending a mail to . - force all output to stdout (some OK/SAY/WARN messages were sent to stdout, some to stderr) - uninstrumented mode uses an internal forkserver ("fauxserver") - - reduced number of (de)allocations + - now builds with `-D_FORTIFY_SOURCE=2` + - drastically reduced number of (de)allocations during fuzzing - afl-fuzz: - python mutator modules and custom mutator modules now use the same interface and hence the API changed @@ -205,7 +206,7 @@ sending a mail to . - big code refactoring: * all includes are now in include/ - * all afl sources are now in src/ - see src/README.src + * all afl sources are now in src/ - see src/README.md * afl-fuzz was splitted up in various individual files for including functionality in other programs (e.g. forkserver, memory map, etc.) for better readability. diff --git a/include/common.h b/include/common.h index db92e32d..c26740ed 100644 --- a/include/common.h +++ b/include/common.h @@ -101,3 +101,4 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms); #endif + diff --git a/qbdi_mode/build.sh b/qbdi_mode/build.sh index c2912e94..e3786f40 100755 --- a/qbdi_mode/build.sh +++ b/qbdi_mode/build.sh @@ -52,6 +52,6 @@ ${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g echo "[+] Building afl-fuzz for Android" # build afl-fuzz cd .. -${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w +${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-state.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w echo "[+] All done. Enjoy!" diff --git a/src/README.md b/src/README.md new file mode 100644 index 00000000..6da534c3 --- /dev/null +++ b/src/README.md @@ -0,0 +1,24 @@ +# Source Folder + +Quick explanation about the files here: + +- `afl-analyze.c` - afl-analyze binary tool +- `afl-as.c` - afl-as binary tool +- `afl-gotcpu.c` - afl-gotcpu binary tool +- `afl-showmap.c` - afl-showmap binary tool +- `afl-tmin.c` - afl-tmin binary tool +- `afl-fuzz.c` - afl-fuzz binary tool (just main() and usage()) +- `afl-fuzz-bitmap.c` - afl-fuzz bitmap handling +- `afl-fuzz-extras.c` - afl-fuzz the *extra* function calls +- `afl-fuzz-state.c` - afl-fuzz state and globals +- `afl-fuzz-init.c` - afl-fuzz initialization +- `afl-fuzz-misc.c` - afl-fuzz misc functions +- `afl-fuzz-one.c` - afl-fuzz fuzzer_one big loop, this is where the mutation is happening +- `afl-fuzz-python.c` - afl-fuzz the python mutator extension +- `afl-fuzz-queue.c` - afl-fuzz handling the queue +- `afl-fuzz-run.c` - afl-fuzz running the target +- `afl-fuzz-stats.c` - afl-fuzz writing the statistics file +- `afl-gcc.c` - afl-gcc binary tool (deprecated) +- `afl-common.c` - common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin +- `afl-forkserver.c` - forkserver implementation, used by afl-fuzz and afl-tmin +afl-sharedmem.c - sharedmem implementation, used by afl-fuzz and afl-tmin diff --git a/src/README.src b/src/README.src deleted file mode 100644 index 244f5ddd..00000000 --- a/src/README.src +++ /dev/null @@ -1,22 +0,0 @@ -Quick explanation about the files here: - -afl-analyze.c - afl-analyze binary tool -afl-as.c - afl-as binary tool -afl-gotcpu.c - afl-gotcpu binary tool -afl-showmap.c - afl-showmap binary tool -afl-tmin.c - afl-tmin binary tool -afl-fuzz.c - afl-fuzz binary tool (just main() and usage()) -afl-fuzz-bitmap.c - afl-fuzz bitmap handling -afl-fuzz-extras.c - afl-fuzz the *extra* function calls -afl-fuzz-globals.c - afl-fuzz global variables -afl-fuzz-init.c - afl-fuzz initialization -afl-fuzz-misc.c - afl-fuzz misc functions -afl-fuzz-one.c - afl-fuzz fuzzer_one big loop, this is where the mutation is happening -afl-fuzz-python.c - afl-fuzz the python mutator extension -afl-fuzz-queue.c - afl-fuzz handling the queue -afl-fuzz-run.c - afl-fuzz running the target -afl-fuzz-stats.c - afl-fuzz writing the statistics file -afl-gcc.c - afl-gcc binary tool (deprecated) -afl-common.c - common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin -afl-forkserver.c - forkserver implementation, used by afl-fuzz and afl-tmin -afl-sharedmem.c - sharedmem implementation, used by afl-fuzz and afl-tmin diff --git a/src/afl-common.c b/src/afl-common.c index 785d7c4c..c73d8725 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -423,7 +423,7 @@ u64 get_cur_time_us(void) { Will return buf for convenience. */ u8 *stringify_int(u8 *buf, size_t len, u64 val) { - +\ #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ do { \ \ @@ -583,7 +583,7 @@ u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { Will return buf for convenience. */ u8 *u_stringify_int(u8 *buf, u64 val) { - +\ #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ do { \ \ @@ -783,3 +783,4 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { : 1; // at least 1 milli must have passed (0 is an error) } + diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-state.c similarity index 100% rename from src/afl-fuzz-globals.c rename to src/afl-fuzz-state.c From 0a7dc10dd3211ab453111853f5f8c74af29e6372 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 04:22:22 +0200 Subject: [PATCH 75/97] fixed bug in cmplog --- include/afl-fuzz.h | 14 +++++++------- src/afl-fuzz-cmplog.c | 16 ++++++++-------- src/afl-fuzz-run.c | 10 +++++----- src/afl-fuzz-stats.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e750d7c9..47aad5af 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -484,11 +484,6 @@ typedef struct afl_state { unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ total_execs, /* Total execve() calls */ - slowest_exec_ms, /* Slowest testcase non hang in ms */ - start_time, /* Unix start time (ms) */ - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ @@ -496,9 +491,14 @@ typedef struct afl_state { bytes_trim_in, /* Bytes coming into the trimmer */ bytes_trim_out, /* Bytes coming outa the trimmer */ blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ + blocks_eff_select, /* Blocks selected as fuzzable */ + start_time, /* Unix start time (ms) */ + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time; /* Time for most recent hang (ms) */ - u32 subseq_tmouts; /* Number of timeouts in a row */ + u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ + subseq_tmouts; /* Number of timeouts in a row */ u8 *stage_name, /* Name of the current fuzz stage */ *stage_short, /* Short stage name */ diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 08ac15c7..f932f33b 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -187,13 +187,13 @@ void init_cmplog_forkserver(afl_state_t *afl) { rlen = 4; u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; /* Reuse readfds as exceptfds to see when the child closed the pipe */ - u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); + u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); - if (!time_ms) { + if (!exec_ms) { PFATAL("Error in timed read"); - } else if (time_ms > timeout_ms) { + } else if (exec_ms > timeout_ms) { afl->fsrv.child_timed_out = 1; kill(afl->cmplog_fsrv_pid, SIGKILL); @@ -377,7 +377,7 @@ void init_cmplog_forkserver(afl_state_t *afl) { u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { int status = 0; - u64 exec_ms; + u32 exec_ms; u32 tb4; s32 res; @@ -416,9 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ - u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); + exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); - if (time_ms > timeout) { + if (exec_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ @@ -427,11 +427,11 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { afl->fsrv.child_timed_out = 1; /* After killing the child, the forkserver should tell us */ - if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) time_ms = 0; + if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0; } - if (!time_ms) { // Something went wrong. + if (!exec_ms) { // Something went wrong. if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index f58e1a33..8cef78b9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -33,7 +33,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) { s32 res; - u32 time_ms; + u32 exec_ms; int status = 0; u32 tb4; @@ -67,20 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) { if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); + exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); - if (time_ms > timeout) { + if (exec_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ kill(afl->fsrv.child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; - if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) time_ms = 0; + if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0; } - if (!time_ms) { + if (!exec_ms) { if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 7fde2fdc..98a97a34 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -95,7 +95,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "last_hang : %llu\n" "execs_since_crash : %llu\n" "exec_timeout : %u\n" - "slowest_exec_ms : %llu\n" + "slowest_exec_ms : %u\n" "peak_rss_mb : %lu\n" "afl_banner : %s\n" "afl_version : " VERSION From e58e54c2db70472bcc86de39e251a3496f67861d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 04:51:38 +0200 Subject: [PATCH 76/97] make travis happy --- include/afl-fuzz.h | 2 -- include/common.h | 3 +++ src/afl-analyze.c | 7 +++---- src/afl-common.c | 6 ++++-- src/afl-forkserver.c | 2 -- src/afl-fuzz-state.c | 2 -- src/afl-fuzz.c | 2 -- src/afl-showmap.c | 5 +---- src/afl-tmin.c | 6 ++---- 9 files changed, 13 insertions(+), 22 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 47aad5af..357cd854 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -239,8 +239,6 @@ enum { }; -extern u8 *doc_path; /* gath to documentation dir */ - /* Python stuff */ #ifdef USE_PYTHON diff --git a/include/common.h b/include/common.h index c26740ed..c9436e81 100644 --- a/include/common.h +++ b/include/common.h @@ -48,6 +48,9 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); +extern u8 be_quiet; +extern u8 *doc_path; /* path to documentation dir */ + /* Get unix time in milliseconds */ u64 get_cur_time(void); diff --git a/src/afl-analyze.c b/src/afl-analyze.c index d509c43e..473a257d 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -60,10 +60,9 @@ static s32 child_pid; /* PID of the tested program */ u8 *trace_bits; /* SHM with instrumentation bitmap */ static u8 *in_file, /* Analyzer input test case */ - *prog_in, /* Targeted program input file */ - *doc_path; /* Path to docs */ + *prog_in; /* Targeted program input file */ -static u8 *in_data; /* Input data for analysis */ + static u8 *in_data; /* Input data for analysis */ static u32 in_len, /* Input data length */ orig_cksum, /* Original checksum */ @@ -77,7 +76,7 @@ static s32 dev_null_fd = -1; /* FD to /dev/null */ u8 edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ - be_quiet, use_stdin = 1; /* Use stdin for program input? */ + use_stdin = 1; /* Use stdin for program input? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_timed_out; /* Child timed out? */ diff --git a/src/afl-common.c b/src/afl-common.c index c73d8725..920c7dfd 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -38,8 +38,10 @@ #endif #include -extern u8 be_quiet; -char * afl_environment_variables[] = { +u8 be_quiet = 0; +u8 *doc_path = ""; + +char *afl_environment_variables[] = { "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS", "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE", diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 01a606c3..962ca86d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -49,8 +49,6 @@ /* Describe integer as memory size. */ -extern u8 *doc_path; - list_t fsrv_list = {.element_prealloc_count = 0}; /* Initializes the struct */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 1d99e1fa..80176a10 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -34,8 +34,6 @@ char *power_names[POWER_SCHEDULES_NUM] = { "explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"}; -u8 *doc_path = NULL; /* gath to documentation dir */ - /* Initialize MOpt "globals" for this afl state */ static void init_mopt_globals(afl_state_t *afl) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ba56ff67..617a42ec 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -25,8 +25,6 @@ #include "afl-fuzz.h" -u8 be_quiet = 0; - static u8 *get_libradamsa_path(u8 *own_loc) { u8 *tmp, *cp, *rsl, *own_copy; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index eaab5c31..f8a38c36 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -59,13 +59,10 @@ #include #include -u8 be_quiet; - char *stdin_file; /* stdin file */ u8 *in_dir, /* input folder */ - *doc_path, /* Path to docs */ - *at_file = NULL; /* Substitution string for @@ */ + *at_file = NULL; /* Substitution string for @@ */ static u8 *in_data; /* Input data */ diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 2275aef5..8a5e3eef 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -61,8 +61,7 @@ static u8 *mask_bitmap; /* Mask for trace bits (-B) */ u8 *in_file, /* Minimizer input test case */ - *output_file, /* Minimizer output file */ - *doc_path; /* Path to docs */ + *output_file; /* Minimizer output file */ static u8 *in_data; /* Input data for trimming */ @@ -77,8 +76,7 @@ u8 crash_mode, /* Crash-centric mode? */ hang_mode, /* Minimize as long as it hangs */ exit_crash, /* Treat non-zero exit as crash? */ edges_only, /* Ignore hit counts? */ - exact_mode, /* Require path match for crashes? */ - be_quiet; + exact_mode; /* Require path match for crashes? */ static volatile u8 stop_soon; /* Ctrl-C pressed? */ From 3253e3f315bca128ecc257764ee3eeaa7eced8e1 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 31 Mar 2020 07:14:25 +0200 Subject: [PATCH 77/97] fix unit test compilation --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b45cf9d3..aaeb136c 100644 --- a/Makefile +++ b/Makefile @@ -316,7 +316,7 @@ test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittes $(CC) $(CFLAGS) $(CFLAGS_FLTO) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o unit_maybe_alloc: test/unittests/unit_maybe_alloc.o - $(CC) $(CFLAGS) -lcmocka -Wl,--wrap=exit -Wl,--wrap=printf $(LDFLAGS) test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc + $(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $(LDFLAGS) test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc -ldl -lcmocka ./test/unittests/unit_maybe_alloc unit: unit_maybe_alloc From 08b6b4ec4e85d81eff00990ba91989c7662ce825 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 31 Mar 2020 07:37:30 +0200 Subject: [PATCH 78/97] travis: dont fail on custom mutator - currently --- test/test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test.sh b/test/test.sh index de730c15..0dc58cc8 100755 --- a/test/test.sh +++ b/test/test.sh @@ -961,6 +961,8 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS CODE=1 } + test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; } + make -C ../examples/custom_mutators clean > /dev/null 2>&1 rm -f test-custom-mutator } || { From 822e75f7c2a6c7a97de7284d70210be54fc6e038 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 14:01:22 +0200 Subject: [PATCH 79/97] reenabled custom mutator report --- examples/custom_mutators/Makefile | 2 +- llvm_mode/afl-clang-fast.c | 1 - src/afl-fuzz-one.c | 1 + test/test.sh | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/custom_mutators/Makefile b/examples/custom_mutators/Makefile index 463cefb1..9849f3f4 100644 --- a/examples/custom_mutators/Makefile +++ b/examples/custom_mutators/Makefile @@ -1,7 +1,7 @@ all: libexamplemutator.so libexamplemutator.so: - $(CC) $(CFLAGS) -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so + $(CC) $(CFLAGS) -D_FORTIFY_SOURCE=2 -O3 -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so clean: rm -rf libexamplemutator.so diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 99bc8d03..de8d3410 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -48,7 +48,6 @@ static u8 debug; static u8 cwd[4096]; static u8 cmplog_mode; u8 use_stdin = 0; /* dummy */ -u8 be_quiet = 0; u8 *getthecwd() { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 2e49e19b..b20bde90 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1648,6 +1648,7 @@ custom_mutator_stage: } /* `(afl->)out_buf` may have been changed by the call to custom_fuzz */ + /* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs Memcpy. */ memcpy(out_buf, in_buf, len); } diff --git a/test/test.sh b/test/test.sh index 0dc58cc8..a04df384 100755 --- a/test/test.sh +++ b/test/test.sh @@ -961,7 +961,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS CODE=1 } - test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; } + #test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; } make -C ../examples/custom_mutators clean > /dev/null 2>&1 rm -f test-custom-mutator From d0d5518ea893b62c96d26e48a444fd33af56d27c Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 31 Mar 2020 18:06:14 +0200 Subject: [PATCH 80/97] fix gcc --- gcc_plugin/afl-gcc-fast.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gcc_plugin/afl-gcc-fast.c b/gcc_plugin/afl-gcc-fast.c index 3583345e..fbda08b6 100644 --- a/gcc_plugin/afl-gcc-fast.c +++ b/gcc_plugin/afl-gcc-fast.c @@ -41,7 +41,6 @@ static u8 * obj_path; /* Path to runtime libraries */ static u8 **cc_params; /* Parameters passed to the real CC */ static u32 cc_par_cnt = 1; /* Param count, including argv0 */ u8 use_stdin = 0; /* dummy */ -u8 be_quiet; /* Try to find the runtime libraries. If that fails, abort. */ From d73e63bd70d9c857373692365f8efb0f65f13b25 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 01:24:44 +0200 Subject: [PATCH 81/97] try to fix forkserver --- Makefile | 4 ++-- src/afl-forkserver.c | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index aaeb136c..f615c7dd 100644 --- a/Makefile +++ b/Makefile @@ -153,8 +153,8 @@ endif ifdef ASAN_BUILD $(info Compiling ASAN version of binaries) - CFLAGS+=-fsanitize=address - LDFLAGS+=-fsanitize=address + CFLAGS+=-fsanitize=address -fstack-protector-strong + LDFLAGS+=-fsanitize=address -fstack-protector-strong endif ifdef PROFILING diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 962ca86d..a863efcc 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -319,10 +319,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen, fsrv->exec_tmout * FORK_WAIT_MULT); - if (!time) { + if (time > fsrv->exec_tmout * FORK_WAIT_MULT) { fsrv->child_timed_out = 1; - kill(fsrv->child_pid, SIGKILL); + kill(fsrv->fsrv_pid, SIGKILL); + + } + if (!time) { + + kill(fsrv->fsrv_pid, SIGKILL); } From d4c8a2058df7dbf4118efb5280f929a92f034961 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 01:38:45 +0200 Subject: [PATCH 82/97] fixed docu --- include/afl-fuzz.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 357cd854..a9165064 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -713,8 +713,8 @@ struct custom_mutator { * * @param data pointer returned in afl_custom_init for this fuzz case * @param[out] out_buf Pointer to the buffer containing the trimmed test case. - * External library should allocate memory for out_buf. AFL++ will release - * the memory after saving the test case. + * The library can reuse a buffer for each call + * and will have to free the buf (for example in deinit) * @return the size of the trimmed test case */ size_t (*afl_custom_trim)(void *data, u8 **out_buf); From 7f44fec0a5c4391b6835310262cd28823707533d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 01:55:13 +0200 Subject: [PATCH 83/97] minor changes --- afl-whatsup | 4 ++-- src/afl-fuzz-init.c | 2 +- test/unittests/unit_maybe_alloc.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/afl-whatsup b/afl-whatsup index c3017689..1a276964 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -171,8 +171,8 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes)) TOTAL_PENDING=$((TOTAL_PENDING + pending_total)) TOTAL_PFAV=$((TOTAL_PFAV + pending_favs)) - - if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then + + if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then TOTAL_LAST_PATH=$last_path fi diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index fe2be4d2..e2495524 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -391,7 +391,7 @@ void read_testcases(afl_state_t *afl) { if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { - free(fn2); + ck_free(fn2); continue; } diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index 93f10889..25b41d46 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -137,4 +137,4 @@ int main(int argc, char **argv) { return cmocka_run_group_tests (tests, setup, teardown); -} \ No newline at end of file +} From 11cad9fb20cb1a10351d198ef35e09541fd83919 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 01:58:34 +0200 Subject: [PATCH 84/97] one less alloc --- src/afl-fuzz-run.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 8cef78b9..08d8b615 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -168,19 +168,15 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; - char *fn = alloc_printf("%s/mutations/%09u:%s", afl->out_dir, + char fn[PATH_MAX]; + snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir, afl->document_counter++, describe_op(afl, 0)); - if (fn != NULL) { - if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { + if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { - if (write(doc_fd, mem, len) != len) - PFATAL("write to mutation file failed: %s", fn); - close(doc_fd); - - } - - ck_free(fn); + if (write(doc_fd, mem, len) != len) + PFATAL("write to mutation file failed: %s", fn); + close(doc_fd); } From 0349b0a735fe28cd831dcab4098b676ab44347ca Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:00:03 +0200 Subject: [PATCH 85/97] code format --- src/afl-analyze.c | 2 +- src/afl-forkserver.c | 5 +---- src/afl-fuzz-run.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 473a257d..427fbe6d 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -62,7 +62,7 @@ u8 *trace_bits; /* SHM with instrumentation bitmap */ static u8 *in_file, /* Analyzer input test case */ *prog_in; /* Targeted program input file */ - static u8 *in_data; /* Input data for analysis */ +static u8 *in_data; /* Input data for analysis */ static u32 in_len, /* Input data length */ orig_cksum, /* Original checksum */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a863efcc..11b359da 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -325,11 +325,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { kill(fsrv->fsrv_pid, SIGKILL); } - if (!time) { - kill(fsrv->fsrv_pid, SIGKILL); - - } + if (!time) { kill(fsrv->fsrv_pid, SIGKILL); } } else { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 08d8b615..2caea123 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -167,7 +167,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { s32 fd = afl->fsrv.out_fd; #ifdef _AFL_DOCUMENT_MUTATIONS - s32 doc_fd; + s32 doc_fd; char fn[PATH_MAX]; snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir, afl->document_counter++, describe_op(afl, 0)); From ead3701f5ba4725c1daf3301baa4add91b1c0147 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:03:46 +0200 Subject: [PATCH 86/97] next_p2 replaced by next_pow2 --- src/afl-fuzz-queue.c | 6 +++--- src/afl-fuzz-run.c | 4 ++-- src/afl-tmin.c | 15 ++------------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4f1bd041..61bf62f5 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -184,7 +184,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u32 i; u64 fav_factor; - u64 fuzz_p2 = next_p2(q->n_fuzz); + u64 fuzz_p2 = next_pow2(q->n_fuzz); if (afl->schedule == MMOPT || afl->schedule == RARE) fav_factor = q->len << 2; @@ -201,7 +201,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { /* Faster-executing or smaller test cases are favored. */ u64 top_rated_fav_factor; - u64 top_rated_fuzz_p2 = next_p2(afl->top_rated[i]->n_fuzz); + u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz); if (afl->schedule == MMOPT || afl->schedule == RARE) top_rated_fav_factor = afl->top_rated[i]->len << 2; @@ -440,7 +440,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { if (q->fuzz_level < 16) factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); else - factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2(fuzz)); + factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz)); break; case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2caea123..5875eb68 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -608,7 +608,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Select initial chunk len, starting with large steps. */ - len_p2 = next_p2(q->len); + len_p2 = next_pow2(q->len); remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES); @@ -653,7 +653,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u32 move_tail = q->len - remove_pos - trim_avail; q->len -= trim_avail; - len_p2 = next_p2(q->len); + len_p2 = next_pow2(q->len); memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail, move_tail); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 8a5e3eef..30e76d42 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -404,17 +404,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } -/* Find first power of two greater or equal to val. */ - -static u32 next_p2(u32 val) { - - u32 ret = 1; - while (val > ret) - ret <<= 1; - return ret; - -} - /* Actually minimize! */ static void minimize(afl_forkserver_t *fsrv, char **argv) { @@ -432,7 +421,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) { * BLOCK NORMALIZATION * ***********************/ - set_len = next_p2(in_len / TMIN_SET_STEPS); + set_len = next_pow2(in_len / TMIN_SET_STEPS); set_pos = 0; if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE; @@ -482,7 +471,7 @@ next_pass: * BLOCK DELETION * ******************/ - del_len = next_p2(in_len / TRIM_START_STEPS); + del_len = next_pow2(in_len / TRIM_START_STEPS); stage_o_len = in_len; ACTF(cBRI "Stage #1: " cRST "Removing blocks of data..."); From 98c090818576a738c910a7dcd50540f60904d3a2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:07:52 +0200 Subject: [PATCH 87/97] docs --- examples/README.md | 2 +- examples/custom_mutators/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/README.md b/examples/README.md index 6c09caeb..3c5aa9f2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,7 +2,7 @@ Here's a quick overview of the stuff you can find in this directory: - - custom_mutstors - An example custom mutator + - custom_mutators - example custom mutators in python an c - argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed (e.g., to test setuid programs). diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md index e5af5516..15c6ffc5 100644 --- a/examples/custom_mutators/README.md +++ b/examples/custom_mutators/README.md @@ -4,7 +4,7 @@ These are example and helper files for the custom mutator feature. See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information Note that if you compile with python3.7 you must use python3 scripts, and if -you use pyton2.7 to compile python2 scripts! +you use python2.7 to compile python2 scripts! example.c - this is a simple example written in C and should be compiled to a shared library. Use make to compile it and produce libexamplemutator.so From acf4b0981eaa41eb3d2adbf2df0848f0bd33dd55 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:09:33 +0200 Subject: [PATCH 88/97] typo fix --- docs/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 1b97812c..72336b11 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -34,7 +34,7 @@ sending a mail to . the last 5 queue entries - rare: puts focus on queue entries that hits rare branches, also ignores runtime - - llvm_mode: added Control Flow Integrity sanatizer (AFL_USE_CFISAN) + - llvm_mode: added Control Flow Integrity sanitizer (AFL_USE_CFISAN) - LTO collision free instrumented added in llvm_mode with afl-clang-lto - note that this mode is amazing, but quite some targets won't compile - Added llvm_mode NGRAM prev_loc coverage by Adrean Herrera From 101c5a275f0db5edd45f14be6bebb52ea9c0b006 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:28:54 +0200 Subject: [PATCH 89/97] add assert_ptr_equal fallback --- test/unittests/unit_maybe_alloc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index 25b41d46..985e28f7 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -4,6 +4,14 @@ #include #include +/* Apparently not supported in very old cmocka versions */ +#ifndef assert_ptr_equal +#define assert_ptr_equal(a, b) \ + _assert_int_equal(cast_ptr_to_largest_integral_type(a), \ + cast_ptr_to_largest_integral_type(b), \ + __FILE__, __LINE__) +#endif + extern void mock_assert(const int result, const char* const expression, const char * const file, const int line); #undef assert From c843085a28a647fa30f1fcdd437decf71a3b228d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 02:59:19 +0200 Subject: [PATCH 90/97] old cmocka is old --- test/unittests/unit_maybe_alloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index 985e28f7..8fa986d8 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -2,15 +2,17 @@ #include #include #include -#include - -/* Apparently not supported in very old cmocka versions */ +/* cmocka < 1.0 didn't support these features we need */ #ifndef assert_ptr_equal #define assert_ptr_equal(a, b) \ _assert_int_equal(cast_ptr_to_largest_integral_type(a), \ cast_ptr_to_largest_integral_type(b), \ __FILE__, __LINE__) +#define CMUnitTest UnitTest +#define cmocka_unit_test unit_test #endif +#include + extern void mock_assert(const int result, const char* const expression, const char * const file, const int line); From 10b226418c5111a44370951110fac23e99c4e8fb Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 03:20:22 +0200 Subject: [PATCH 91/97] mocking cmocka 1 for cmocka 0.x --- test/unittests/unit_maybe_alloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index 8fa986d8..dcab5baf 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -10,6 +10,7 @@ __FILE__, __LINE__) #define CMUnitTest UnitTest #define cmocka_unit_test unit_test +#define cmocka_run_group_tests(t, setup, teardown) run_tests(t) #endif #include From cec3d744971ee1d7a9301bf7a9ebdd02c955846f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 03:39:36 +0200 Subject: [PATCH 92/97] cmocka mocks --- test/unittests/unit_maybe_alloc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index dcab5baf..7c6cfaaa 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -39,11 +39,13 @@ int __wrap_printf(const char *format, ...) { #define BUF_PARAMS (void **)&buf, &size +/* static int setup(void **state) { return 0; } +*/ static void test_null_allocs(void **state) { @@ -130,11 +132,13 @@ static void test_grow_multiple(void **state) { } +/* static int teardown(void **state) { return 0; } +*/ int main(int argc, char **argv) { @@ -146,6 +150,7 @@ int main(int argc, char **argv) { cmocka_unit_test(test_grow_multiple), }; - return cmocka_run_group_tests (tests, setup, teardown); + //return cmocka_run_group_tests (tests, setup, teardown); + return cmocka_run_group_tests (tests, NULL, NULL); } From c7818714acc8c8dd491c2da98eab06b0db6fbfa0 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 1 Apr 2020 09:42:40 +0200 Subject: [PATCH 93/97] fix cmocka fixup --- test/unittests/unit_maybe_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index 7c6cfaaa..6a165dd4 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -2,6 +2,7 @@ #include #include #include +#include /* cmocka < 1.0 didn't support these features we need */ #ifndef assert_ptr_equal #define assert_ptr_equal(a, b) \ @@ -12,7 +13,6 @@ #define cmocka_unit_test unit_test #define cmocka_run_group_tests(t, setup, teardown) run_tests(t) #endif -#include extern void mock_assert(const int result, const char* const expression, From a5c09e4c114144daaecf2ba1d69cac1c6c75f500 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 1 Apr 2020 12:19:54 +0200 Subject: [PATCH 94/97] disable memory limits for ASAN build --- Makefile | 2 +- src/afl-fuzz.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f615c7dd..5023a72f 100644 --- a/Makefile +++ b/Makefile @@ -153,7 +153,7 @@ endif ifdef ASAN_BUILD $(info Compiling ASAN version of binaries) - CFLAGS+=-fsanitize=address -fstack-protector-strong + CFLAGS+=-fsanitize=address -fstack-protector-strong -D_ASAN_BUILD=1 LDFLAGS+=-fsanitize=address -fstack-protector-strong endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 617a42ec..64644b64 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -721,6 +721,13 @@ int main(int argc, char **argv_orig, char **envp) { } +#ifdef _ASAN_BUILD + if (!afl->fsrv.mem_limit) { + WARNF("in the ASAN build we disable all memory limits"); + afl->fsrv.mem_limit = 0; + } +#endif + setup_signal_handlers(); check_asan_opts(); From ba4f0186dd388cc7abe6691dfc37db49075b80ec Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 12:43:26 +0200 Subject: [PATCH 95/97] fixed asan mem limit --- Makefile | 2 +- src/afl-fuzz.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5023a72f..f615c7dd 100644 --- a/Makefile +++ b/Makefile @@ -153,7 +153,7 @@ endif ifdef ASAN_BUILD $(info Compiling ASAN version of binaries) - CFLAGS+=-fsanitize=address -fstack-protector-strong -D_ASAN_BUILD=1 + CFLAGS+=-fsanitize=address -fstack-protector-strong LDFLAGS+=-fsanitize=address -fstack-protector-strong endif diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 64644b64..68392b05 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -721,7 +721,7 @@ int main(int argc, char **argv_orig, char **envp) { } -#ifdef _ASAN_BUILD +#if defined(__SANITIZE_ADDRESS__) if (!afl->fsrv.mem_limit) { WARNF("in the ASAN build we disable all memory limits"); afl->fsrv.mem_limit = 0; From c4c13dd23549fc8ea45a80823d1bfe96cca6dbcb Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 1 Apr 2020 12:52:54 +0200 Subject: [PATCH 96/97] fix ASAN check --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 68392b05..6e86285d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -722,7 +722,7 @@ int main(int argc, char **argv_orig, char **envp) { } #if defined(__SANITIZE_ADDRESS__) - if (!afl->fsrv.mem_limit) { + if (afl->fsrv.mem_limit) { WARNF("in the ASAN build we disable all memory limits"); afl->fsrv.mem_limit = 0; } From af60844aea1ddc9892eb2b6fc841e92333483c27 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 1 Apr 2020 12:53:03 +0200 Subject: [PATCH 97/97] fix ASAN bulid for old gcc versions --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f615c7dd..c60b7997 100644 --- a/Makefile +++ b/Makefile @@ -153,8 +153,8 @@ endif ifdef ASAN_BUILD $(info Compiling ASAN version of binaries) - CFLAGS+=-fsanitize=address -fstack-protector-strong - LDFLAGS+=-fsanitize=address -fstack-protector-strong + CFLAGS+=-fsanitize=address -fstack-protector-all + LDFLAGS+=-fsanitize=address -fstack-protector-all endif ifdef PROFILING