aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRishi Ranjan <43873720+rish9101@users.noreply.github.com>2020-05-08 23:38:27 +0530
committerGitHub <noreply@github.com>2020-05-08 20:08:27 +0200
commit190f3024dad3713a1b2d3a42b5b99c662dd2cf58 (patch)
tree4c7bb683bbc62e81c52f68d656f583a94cdd014e /src
parent768053b6f25d5abd1b25f104e0233421bd1f73f9 (diff)
downloadafl++-190f3024dad3713a1b2d3a42b5b99c662dd2cf58.tar.gz
Support multiple custom mutators (#282)
* Make a list of custom mutators using env variable * Set up multiple custom mutators * Add destroy custom mutator and changes to load_custom_mutator * Use array instead of list, make changes to afl-fuzz-one for multiple mutators * Make change to fuzz-one custom_queue_get to support multiple mutators * Modify custom python mutator support * Fix bug * Fix missing afl->mutator->data * Revert to list with max count * Change custom_pre_save hook and code format * Free custom_mutator struct in the list * Add testcase for multiple custom mutators * Resolve merge conflict
Diffstat (limited to 'src')
-rw-r--r--src/afl-fuzz-mutators.c193
-rw-r--r--src/afl-fuzz-one.c193
-rw-r--r--src/afl-fuzz-python.c40
-rw-r--r--src/afl-fuzz-queue.c17
-rw-r--r--src/afl-fuzz-run.c49
-rw-r--r--src/afl-fuzz-stats.c2
-rw-r--r--src/afl-fuzz.c4
7 files changed, 274 insertions, 224 deletions
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index beb89092..23f15945 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -26,27 +26,47 @@
#include "afl-fuzz.h"
-void load_custom_mutator(afl_state_t *, const char *);
+struct custom_mutator *load_custom_mutator(afl_state_t *, const char *);
+#ifdef USE_PYTHON
+struct custom_mutator * load_custom_mutator_py(afl_state_t *, char *);
+#endif
-void setup_custom_mutator(afl_state_t *afl) {
+void setup_custom_mutators(afl_state_t *afl) {
/* Try mutator library first */
- u8 *fn = afl->afl_env.afl_custom_mutator_library;
+ struct custom_mutator * mutator;
+ u8 * fn = getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
+ u32 prev_mutator_count = 0;
if (fn) {
- if (afl->limit_time_sig) {
-
+ if (afl->limit_time_sig)
FATAL(
"MOpt and custom mutator are mutually exclusive. We accept pull "
"requests that integrates MOpt with the optional mutators "
"(custom/radamsa/redquenn/...).");
- }
+ u8 *fn_token = (u8 *)strsep((char **)&fn, ";");
+
+ if (likely(!fn_token)) {
- load_custom_mutator(afl, fn);
+ mutator = load_custom_mutator(afl, fn);
+ list_append(&afl->custom_mutator_list, mutator);
+ afl->custom_mutators_count++;
- return;
+ } else {
+
+ while (fn_token) {
+
+ prev_mutator_count = afl->custom_mutators_count;
+ mutator = load_custom_mutator(afl, fn_token);
+ list_append(&afl->custom_mutator_list, mutator);
+ afl->custom_mutators_count++;
+ if (prev_mutator_count > afl->custom_mutators_count) FATAL("Maximum Custom Mutator count reached.");
+ fn_token = (u8 *)strsep((char **)&fn, ";");
+
+ }
+ }
}
@@ -65,7 +85,9 @@ void setup_custom_mutator(afl_state_t *afl) {
}
- load_custom_mutator_py(afl, module_name);
+ struct custom_mutator * mutator = load_custom_mutator_py(afl, module_name);
+ afl->custom_mutators_count++;
+ list_append(&afl->custom_mutator_list, mutator);
}
@@ -80,114 +102,85 @@ void setup_custom_mutator(afl_state_t *afl) {
}
-void destroy_custom_mutator(afl_state_t *afl) {
-
- if (afl->mutator) {
+void destroy_custom_mutators(afl_state_t *afl) {
- afl->mutator->afl_custom_deinit(afl->mutator->data);
+ if (afl->custom_mutators_count) {
- if (afl->mutator->dh) { dlclose(afl->mutator->dh); }
+ LIST_FOREACH_CLEAR(&afl->custom_mutator_list, struct custom_mutator, {
- if (afl->mutator->pre_save_buf) {
+ if (!el->data) { FATAL("Deintializing NULL mutator"); }
+ el->afl_custom_deinit(el->data);
+ if (el->dh) dlclose(el->dh);
- ck_free(afl->mutator->pre_save_buf);
- afl->mutator->pre_save_buf = NULL;
- afl->mutator->pre_save_size = 0;
+ if (el->pre_save_buf) {
+ ck_free(el->pre_save_buf);
+ el->pre_save_buf = NULL;
+ el->pre_save_size = 0;
+ }
- }
+ ck_free(el);
- ck_free(afl->mutator);
- afl->mutator = NULL;
+ } );
}
}
-void load_custom_mutator(afl_state_t *afl, const char *fn) {
+struct custom_mutator *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;
+ void * dh;
+ struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
- afl->mutator->name = fn;
+ mutator->name = fn;
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
- if (!dh) { FATAL("%s", dlerror()); }
- afl->mutator->dh = dh;
+ if (!dh) FATAL("%s", dlerror());
+ mutator->dh = dh;
/* 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.");
-
- }
-
- /* "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.");
-
- }
+ /* "afl_custom_init", optional for backward compatibility */
+ mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
+ if (!mutator->afl_custom_init) WARNF("Symbol 'afl_custom_init' not found.");
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
- afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
- if (!afl->mutator->afl_custom_fuzz) {
+ mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
+ if (!mutator->afl_custom_fuzz) {
/* Try "afl_custom_mutator" for backward compatibility */
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
- afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
- if (!afl->mutator->afl_custom_fuzz) {
-
+ mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
+ if (!mutator->afl_custom_fuzz)
FATAL("Symbol 'afl_custom_mutator' not found.");
- }
-
}
/* "afl_custom_pre_save", optional */
- afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
- if (!afl->mutator->afl_custom_pre_save) {
-
+ mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
+ if (!mutator->afl_custom_pre_save)
WARNF("Symbol 'afl_custom_pre_save' not found.");
- }
-
u8 notrim = 0;
/* "afl_custom_init_trim", optional */
- afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
- if (!afl->mutator->afl_custom_init_trim) {
-
+ mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
+ if (!mutator->afl_custom_init_trim)
WARNF("Symbol 'afl_custom_init_trim' not found.");
- }
-
/* "afl_custom_trim", optional */
- afl->mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
- if (!afl->mutator->afl_custom_trim) {
-
- WARNF("Symbol 'afl_custom_trim' not found.");
-
- }
+ mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
+ if (!mutator->afl_custom_trim) WARNF("Symbol 'afl_custom_trim' not found.");
/* "afl_custom_post_trim", optional */
- afl->mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
- if (!afl->mutator->afl_custom_post_trim) {
-
+ mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
+ if (!mutator->afl_custom_post_trim)
WARNF("Symbol 'afl_custom_post_trim' not found.");
- }
-
if (notrim) {
- afl->mutator->afl_custom_init_trim = NULL;
- afl->mutator->afl_custom_trim = NULL;
- afl->mutator->afl_custom_post_trim = NULL;
+ mutator->afl_custom_init_trim = NULL;
+ mutator->afl_custom_trim = NULL;
+ mutator->afl_custom_post_trim = NULL;
WARNF(
"Custom mutator does not implement all three trim APIs, standard "
"trimming will be used.");
@@ -195,53 +188,41 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
}
/* "afl_custom_havoc_mutation", optional */
- afl->mutator->afl_custom_havoc_mutation =
- dlsym(dh, "afl_custom_havoc_mutation");
- if (!afl->mutator->afl_custom_havoc_mutation) {
-
+ mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
+ if (!mutator->afl_custom_havoc_mutation)
WARNF("Symbol 'afl_custom_havoc_mutation' not found.");
- }
-
/* "afl_custom_havoc_mutation", optional */
- afl->mutator->afl_custom_havoc_mutation_probability =
+ mutator->afl_custom_havoc_mutation_probability =
dlsym(dh, "afl_custom_havoc_mutation_probability");
- if (!afl->mutator->afl_custom_havoc_mutation_probability) {
-
+ if (!mutator->afl_custom_havoc_mutation_probability)
WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found.");
- }
-
/* "afl_custom_queue_get", optional */
- afl->mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
- if (!afl->mutator->afl_custom_queue_get) {
-
+ mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
+ if (!mutator->afl_custom_queue_get)
WARNF("Symbol 'afl_custom_queue_get' not found.");
- }
-
/* "afl_custom_queue_new_entry", optional */
- afl->mutator->afl_custom_queue_new_entry =
- dlsym(dh, "afl_custom_queue_new_entry");
- if (!afl->mutator->afl_custom_queue_new_entry) {
-
+ mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
+ if (!mutator->afl_custom_queue_new_entry)
WARNF("Symbol 'afl_custom_queue_new_entry' not found");
- }
-
OKF("Custom mutator '%s' installed successfully.", fn);
/* Initialize the custom mutator */
- if (afl->mutator->afl_custom_init) {
+ if (mutator->afl_custom_init)
+ mutator->data =
+ mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
- afl->mutator->data =
- afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
+ mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
+ mutator->stacked_custom_prob = 6; // like one of the default mutations in havoc
- }
+ return mutator;
}
-u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
+u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, struct custom_mutator *mutator) {
u8 needs_write = 0, fault = 0;
u32 trim_exec = 0;
@@ -255,7 +236,7 @@ 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);
+ mutator->afl_custom_init_trim(mutator->data, in_buf, q->len);
if (unlikely(afl->stage_max) < 0) {
FATAL("custom_init_trim error ret: %d", afl->stage_max);
@@ -278,7 +259,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
u32 cksum;
- size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
+ size_t retlen = mutator->afl_custom_trim(mutator->data, &retbuf);
if (unlikely(!retbuf)) {
@@ -319,7 +300,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->mutator->data, 1);
+ mutator->afl_custom_post_trim(mutator->data, 1);
if (afl->not_on_tty && afl->debug) {
@@ -332,7 +313,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);
+ mutator->afl_custom_post_trim(mutator->data, 0);
if (unlikely(afl->stage_cur < 0)) {
FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 6d399a03..dff1606a 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -384,17 +384,17 @@ u8 fuzz_one_original(afl_state_t *afl) {
#else
- if (unlikely(afl->mutator) && unlikely(afl->mutator->afl_custom_queue_get)) {
+ if (unlikely(afl->custom_mutators_count )) {
/* 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)) {
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
- return 1;
-
- }
+ if (el->afl_custom_queue_get && !el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
+ return 1;
+ }
+ } );
}
if (likely(afl->pending_favored)) {
@@ -1646,13 +1646,13 @@ custom_mutator_stage:
* CUSTOM MUTATORS *
*******************/
- if (likely(!afl->mutator)) { goto havoc_stage; }
- if (likely(!afl->mutator->afl_custom_fuzz)) { goto havoc_stage; }
+ if (likely(!afl->custom_mutators_count)) { goto havoc_stage; }
afl->stage_name = "custom mutator";
afl->stage_short = "custom";
afl->stage_max = HAVOC_CYCLES * perf_score / afl->havoc_div / 100;
afl->stage_val_type = STAGE_VAL_NONE;
+ bool has_custom_fuzz = false;
if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
@@ -1660,98 +1660,111 @@ custom_mutator_stage:
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
- for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+ LIST_FOREACH (&afl->custom_mutator_list, struct custom_mutator, {
- struct queue_entry *target;
- u32 tid;
- u8 * new_buf;
+ if ( el->afl_custom_fuzz ) {
- retry_external_pick:
- /* Pick a random other queue entry for passing to external API */
- do {
+ has_custom_fuzz = true;
- tid = rand_below(afl, afl->queued_paths);
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
- } while (tid == afl->current_entry && afl->queued_paths > 1);
+ struct queue_entry *target;
+ u32 tid;
+ u8 * new_buf;
- target = afl->queue;
+ retry_external_pick:
+ /* Pick a random other queue entry for passing to external API */
+ do {
- while (tid >= 100) {
+ tid = rand_below(afl, afl->queued_paths);
- target = target->next_100;
- tid -= 100;
+ } while (tid == afl->current_entry && afl->queued_paths > 1);
- }
+ target = afl->queue;
- while (tid--) {
+ while (tid >= 100) {
- target = target->next;
+ target = target->next_100;
+ tid -= 100;
- }
+ }
- /* Make sure that the target has a reasonable length. */
+ while (tid--) {
- while (target && (target->len < 2 || target == afl->queue_cur) &&
- afl->queued_paths > 1) {
+ target = target->next;
- target = target->next;
- ++afl->splicing_with;
+ }
- }
+ /* Make sure that the target has a reasonable length. */
- if (!target) { goto retry_external_pick; }
+ while (target && (target->len < 2 || target == afl->queue_cur) &&
+ afl->queued_paths > 1) {
- /* 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); }
+ target = target->next;
+ ++afl->splicing_with;
- new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
- ck_read(fd, new_buf, target->len, target->fname);
- close(fd);
+ }
- u8 *mutated_buf = NULL;
+ if (!target) { goto retry_external_pick; }
- size_t mutated_size = afl->mutator->afl_custom_fuzz(
- afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
- max_seed_size);
+ /* 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); }
- if (unlikely(!mutated_buf)) {
+ new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
+ ck_read(fd, new_buf, target->len, target->fname);
+ close(fd);
- FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
+ u8 *mutated_buf = NULL;
- }
+ size_t mutated_size = el->afl_custom_fuzz(
+ el->data, out_buf, len, &mutated_buf, new_buf, target->len,
+ max_seed_size);
- if (mutated_size > 0) {
+ if (unlikely(!mutated_buf)) {
- if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+ FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
- goto abandon_entry;
+ }
- }
+ if (mutated_size > 0) {
+
+ if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+
+ goto abandon_entry;
+
+ }
- /* If we're finding new stuff, let's run for a bit longer, limits
- permitting. */
+ /* If we're finding new stuff, let's run for a bit longer, limits
+ permitting. */
- if (afl->queued_paths != havoc_queued) {
+ if (afl->queued_paths != havoc_queued) {
- if (perf_score <= afl->havoc_max_mult * 100) {
+ if (perf_score <= afl->havoc_max_mult * 100) {
- afl->stage_max *= 2;
- perf_score *= 2;
+ afl->stage_max *= 2;
+ perf_score *= 2;
+
+ }
+
+ havoc_queued = afl->queued_paths;
+
+ }
}
- havoc_queued = afl->queued_paths;
+ /* `(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);
}
}
- /* `(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);
- }
+ } );
+
+ if (!has_custom_fuzz) goto havoc_stage;
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
@@ -1803,20 +1816,25 @@ havoc_stage:
havoc_queued = afl->queued_paths;
- u8 stacked_custom = (afl->mutator && afl->mutator->afl_custom_havoc_mutation);
- u8 stacked_custom_prob = 6; // like one of the default mutations in havoc
+ if (afl->custom_mutators_count) {
- if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
- stacked_custom_prob =
- afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
- if (stacked_custom_prob > 100) {
+ if (el->stacked_custom && el->afl_custom_havoc_mutation_probability) {
- FATAL(
- "The probability returned by afl_custom_havoc_mutation_propability "
- "has to be in the range 0-100.");
+ el->stacked_custom_prob =
+ el->afl_custom_havoc_mutation_probability(el->data);
+ if (el->stacked_custom_prob > 100) {
- }
+ FATAL(
+ "The probability returned by afl_custom_havoc_mutation_propability "
+ "has to be in the range 0-100.");
+
+ }
+
+ }
+
+ } );
}
@@ -1831,29 +1849,36 @@ havoc_stage:
for (i = 0; i < use_stacking; ++i) {
- if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
+ if (afl->custom_mutators_count) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
- 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(!custom_havoc_buf)) {
+ if (el->stacked_custom && rand_below(afl, 100) < el->stacked_custom_prob) {
- FATAL("Error in custom_havoc (return %zd)", new_len);
+ u8 * custom_havoc_buf = NULL;
+ size_t new_len = el->afl_custom_havoc_mutation(
+ el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
+ if (unlikely(!custom_havoc_buf)) {
- }
+ 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) {
+ if (likely(new_len > 0 && custom_havoc_buf)) {
- ck_maybe_grow(BUF_PARAMS(out), temp_len);
- memcpy(out_buf, custom_havoc_buf, temp_len);
+ 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);
- }
+ }
+
+ }
+ }
+
+ } );
}
switch (rand_below(
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 64cabcad..a65add55 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -295,88 +295,94 @@ void deinit_py(void *py_mutator) {
}
-void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
+struct custom_mutator * 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;
+ struct custom_mutator * mutator;
- afl->mutator->name = module_name;
+ mutator = ck_alloc(sizeof(struct custom_mutator));
+ mutator->pre_save_buf = NULL;
+ mutator->pre_save_size = 0;
+
+ mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
py_mutator_t *py_mutator;
py_mutator = init_py_module(afl, module_name);
- afl->mutator->data = py_mutator;
+ mutator->data = py_mutator;
if (!py_mutator) { FATAL("Failed to load python mutator."); }
PyObject **py_functions = py_mutator->py_functions;
if (py_functions[PY_FUNC_INIT]) {
- afl->mutator->afl_custom_init = unsupported;
+ mutator->afl_custom_init = unsupported;
}
if (py_functions[PY_FUNC_DEINIT]) {
- afl->mutator->afl_custom_deinit = deinit_py;
+ mutator->afl_custom_deinit = deinit_py;
}
/* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
is quite different from the custom mutator. */
- afl->mutator->afl_custom_fuzz = fuzz_py;
+ mutator->afl_custom_fuzz = fuzz_py;
if (py_functions[PY_FUNC_PRE_SAVE]) {
- afl->mutator->afl_custom_pre_save = pre_save_py;
+ mutator->afl_custom_pre_save = pre_save_py;
}
if (py_functions[PY_FUNC_INIT_TRIM]) {
- afl->mutator->afl_custom_init_trim = init_trim_py;
+ mutator->afl_custom_init_trim = init_trim_py;
}
if (py_functions[PY_FUNC_POST_TRIM]) {
- afl->mutator->afl_custom_post_trim = post_trim_py;
+ mutator->afl_custom_post_trim = post_trim_py;
}
- if (py_functions[PY_FUNC_TRIM]) { afl->mutator->afl_custom_trim = trim_py; }
+ if (py_functions[PY_FUNC_TRIM]) { mutator->afl_custom_trim = trim_py; }
if (py_functions[PY_FUNC_HAVOC_MUTATION]) {
- afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
+ mutator->afl_custom_havoc_mutation = havoc_mutation_py;
}
if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) {
- afl->mutator->afl_custom_havoc_mutation_probability =
+ mutator->afl_custom_havoc_mutation_probability =
havoc_mutation_probability_py;
}
if (py_functions[PY_FUNC_QUEUE_GET]) {
- afl->mutator->afl_custom_queue_get = queue_get_py;
+ mutator->afl_custom_queue_get = queue_get_py;
}
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) {
- afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
+ mutator->afl_custom_queue_new_entry = queue_new_entry_py;
}
+
+
OKF("Python mutator '%s' installed successfully.", module_name);
/* Initialize the custom mutator */
init_py(afl, py_mutator, rand_below(afl, 0xFFFFFFFF));
+ return mutator;
+
}
size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f998c06b..c33751d9 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -140,15 +140,20 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
afl->last_path_time = get_cur_time();
- if (afl->mutator && afl->mutator->afl_custom_queue_new_entry) {
+ if (afl->custom_mutators_count) {
- u8 *fname_orig = NULL;
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
- /* At the initialization stage, queue_cur is NULL */
- if (afl->queue_cur) { fname_orig = afl->queue_cur->fname; }
+ if ( el->afl_custom_queue_new_entry) {
+ u8 *fname_orig = NULL;
- afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
- fname_orig);
+ /* At the initialization stage, queue_cur is NULL */
+ if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
+
+ el->afl_custom_queue_new_entry(el->data, fname, fname_orig);
+ }
+
+ } );
}
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index b7f7f29c..3876dec7 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -89,21 +89,41 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
#endif
- if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
+ if (unlikely(afl->custom_mutators_count)) {
u8 *new_buf = NULL;
+ ssize_t new_size = len;
+ void * new_mem = mem;
- size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
- len, &new_buf);
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
- if (unlikely(!new_buf)) {
+ if (el->afl_custom_pre_save) {
+ new_size = el->afl_custom_pre_save(
+ el->data, new_mem, new_size, &new_buf
+ );
+
+ }
+
+ new_mem = new_buf;
+
+ } );
+
+ if (unlikely(!new_buf && (new_size <= 0))) {
FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
+ } else if (likely(new_buf)) {
+
+ /* everything as planned. use the new data. */
+ afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size);
+
+ } else {
+
+ /* custom mutators do not has a custom_pre_save function */
+ afl_fsrv_write_to_testcase(&afl->fsrv, mem, len);
+
}
- /* everything as planned. use the new data. */
- afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size);
} else {
@@ -513,10 +533,23 @@ void sync_fuzzers(afl_state_t *afl) {
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
/* Custom mutator trimmer */
- if (afl->mutator && afl->mutator->afl_custom_trim) {
+ if (afl->custom_mutators_count) {
+
+ u8 trimmed_case = 0;
+ bool custom_trimmed = false;
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_trim) {
+
+ trimmed_case = trim_case_custom(afl, q, in_buf, el);
+ custom_trimmed = true;
+ }
- return trim_case_custom(afl, q, in_buf);
+ } );
+ if (custom_trimmed) return trimmed_case;
+
}
u8 needs_write = 0, fault = 0;
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 3cbb2d8c..032cf01d 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -792,7 +792,7 @@ void show_stats(afl_state_t *afl) {
}
- if (afl->mutator) {
+ if (afl->custom_mutators_count) {
sprintf(tmp, "%s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 64973260..14765981 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -1077,7 +1077,7 @@ int main(int argc, char **argv_orig, char **envp) {
setup_dirs_fds(afl);
- setup_custom_mutator(afl);
+ setup_custom_mutators(afl);
setup_cmdline_file(afl, argv + optind);
@@ -1365,7 +1365,7 @@ stop_fuzzing:
fclose(afl->fsrv.plot_file);
destroy_queue(afl);
destroy_extras(afl);
- destroy_custom_mutator(afl);
+ destroy_custom_mutators(afl);
afl_shm_deinit(&afl->shm);
afl_fsrv_deinit(&afl->fsrv);
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }