From c2b04bdf6c596f5d220f27caead20d09452ed42d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Thu, 16 Jul 2020 14:32:41 +0200 Subject: queue buffer and new splice havoc mutation --- src/afl-fuzz-queue.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/afl-fuzz-queue.c') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 7afdd9f1..a96995e5 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -25,6 +25,8 @@ #include "afl-fuzz.h" #include +#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + /* Mark deterministic checks as done for a particular queue entry. We use the .state file to avoid repeating deterministic fuzzing when resuming aborted scans. */ @@ -137,6 +139,9 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { afl->q_prev100 = q; } + + struct queue_entry** queue_buf = ck_maybe_grow(BUF_PARAMS(queue), afl->queued_paths * sizeof(struct queue_entry*)); + queue_buf[afl->queued_paths -1] = q; afl->last_path_time = get_cur_time(); -- cgit 1.4.1 From ce9b4698fec5222e0af1b62d68c4105e6364771e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 21 Jul 2020 20:53:51 +0200 Subject: added andrea's splicing, added cycle_schedules --- GNUmakefile | 2 +- include/afl-fuzz.h | 11 +- include/config.h | 24 ++ include/envs.h | 1 + src/afl-fuzz-one.c | 719 +++++++++++++++++++++++++++++++++++++++++++-------- src/afl-fuzz-queue.c | 112 +++++++- src/afl-fuzz-state.c | 7 + src/afl-fuzz.c | 80 +++++- 8 files changed, 834 insertions(+), 122 deletions(-) (limited to 'src/afl-fuzz-queue.c') diff --git a/GNUmakefile b/GNUmakefile index f44ef95e..86d6a947 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -455,7 +455,7 @@ code-format: ./.custom-format.py -i llvm_mode/*.h ./.custom-format.py -i llvm_mode/*.cc ./.custom-format.py -i gcc_plugin/*.c - #./.custom-format.py -i gcc_plugin/*.h + @#./.custom-format.py -i gcc_plugin/*.h ./.custom-format.py -i gcc_plugin/*.cc ./.custom-format.py -i custom_mutators/*/*.c ./.custom-format.py -i custom_mutators/*/*.h diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index adab8155..96d3d9f4 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -139,7 +139,8 @@ struct queue_entry { var_behavior, /* Variable behavior? */ favored, /* Currently favored? */ fs_redundant, /* Marked as redundant in the fs? */ - fully_colorized; /* Do not run redqueen stage again */ + fully_colorized, /* Do not run redqueen stage again */ + is_ascii; /* Is the input just ascii text? */ u32 bitmap_size, /* Number of bits set in bitmap */ fuzz_level; /* Number of fuzzing iterations */ @@ -333,7 +334,7 @@ typedef struct afl_env_vars { afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child_output, afl_autoresume, - afl_cal_fast; + afl_cal_fast, afl_cycle_schedules; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_skip_crashes, *afl_preload; @@ -454,7 +455,9 @@ typedef struct afl_state { fixed_seed, /* do not reseed */ fast_cal, /* Try to calibrate faster? */ disable_trim, /* Never trim in fuzz_one */ - shmem_testcase_mode; /* If sharedmem testcases are used */ + shmem_testcase_mode, /* If sharedmem testcases are used */ + expand_havoc, /* perform expensive havoc after no find */ + cycle_schedules; /* cycle power schedules ? */ u8 *virgin_bits, /* Regions yet untouched by fuzzing */ *virgin_tmout, /* Bits we haven't seen in tmouts */ @@ -548,7 +551,7 @@ typedef struct afl_state { // growing buf struct queue_entry **queue_buf; - size_t queue_size; + size_t queue_size; struct queue_entry **top_rated; /* Top entries for bitmap bytes */ diff --git a/include/config.h b/include/config.h index 4503c3e9..9710cd1f 100644 --- a/include/config.h +++ b/include/config.h @@ -401,5 +401,29 @@ // #define IGNORE_FINDS +/* Text mutations */ + +/* What is the minimum length of a queue input to be evaluated for "is_ascii"? ++ */ + +#define AFL_TXT_MIN_LEN 12 + +/* What is the minimum percentage of ascii characters present to be classifed + as "is_ascii"? */ + +#define AFL_TXT_MIN_PERCENT 95 + +/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ + +#define AFL_TXT_BIAS 6 + +/* Maximum length of a string to tamper with */ + +#define AFL_TXT_STRING_MAX_LEN 1024 + +/* Maximum mutations on a string */ + +#define AFL_TXT_STRING_MAX_MUTATIONS 8 + #endif /* ! _HAVE_CONFIG_H */ diff --git a/include/envs.h b/include/envs.h index 86222418..cb3c183e 100644 --- a/include/envs.h +++ b/include/envs.h @@ -34,6 +34,7 @@ static char *afl_environment_variables[] = { "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", + "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD_OUTPUT", "AFL_DEBUG_GDB", diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 399bfcab..250409da 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -24,6 +24,11 @@ */ #include "afl-fuzz.h" +#include + +static u8 *strnstr(const u8 *s, const u8 *find, size_t slen); +static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, + u8 *to); /* MOpt */ @@ -362,6 +367,450 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { #endif /* !IGNORE_FINDS */ +#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size + +/* search a string */ + +static u8 *strnstr(const u8 *s, const u8 *find, size_t slen) { + + char c, sc; + size_t len; + + if ((c = *find++) != '\0') { + + len = strlen(find); + do { + + do { + + if (slen-- < 1 || (sc = *s++) == '\0') return (NULL); + + } while (sc != c); + + if (len > slen) return (NULL); + + } while (strncmp(s, find, len) != 0); + + s--; + + } + + return ((u8 *)s); + +} + +/* replace between deliminators, if rep == NULL, then we will duplicate the + * target */ + +static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos, + const u8 *ldelim, const u8 *rdelim, u8 *rep) { + + u8 *end_buf = *out_buf + *temp_len; + u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos); + + if (ldelim_start != NULL) { + + u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : end_buf - ldelim_start - 1); + + if (max > 0) { + + u8 *rdelim_end = strnstr(ldelim_start + 1, rdelim, max); + + if (rdelim_end != NULL) { + + u32 rep_len, delim_space_len = rdelim_end - ldelim_start - 1, xtra = 0; + + if (rep != NULL) { + + rep_len = (u32)strlen(rep); + + } else { // NULL? then we copy the value in between the delimiters + + rep_len = delim_space_len; + delim_space_len = 0; + rep = ldelim_start + 1; + xtra = rep_len; + + } + + if (rep_len != delim_space_len) { + + memmove(ldelim_start + rep_len + xtra + 1, rdelim_end, + *temp_len - (rdelim_end - *out_buf)); + + } + + memcpy(ldelim_start + 1, rep, rep_len); + *temp_len = (*temp_len - delim_space_len + rep_len); + + return 1; + + } + + } + + } + + return 0; + +} + +static u32 delim_swap(u8 **out_buf, s32 *temp_len, size_t pos, const u8 *ldelim, + const u8 *mdelim, const u8 *rdelim) { + + u8 *out_buf_end = *out_buf + *temp_len; + u32 max = (*temp_len - pos > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN + : *temp_len - pos); + u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, max); + + if (ldelim_start != NULL) { + + max = (out_buf_end - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : out_buf_end - ldelim_start - 1); + if (max > 1) { + + u8 *mdelim_pos = strnstr(ldelim_start + 1, mdelim, max); + + if (mdelim_pos != NULL) { + + max = (out_buf_end - mdelim_pos - 1 > AFL_TXT_STRING_MAX_LEN + ? AFL_TXT_STRING_MAX_LEN + : out_buf_end - mdelim_pos - 1); + if (max > 0) { + + u8 *rdelim_end = strnstr(mdelim + 1, rdelim, max); + + if (rdelim_end != NULL) { + + u32 first_len = mdelim_pos - ldelim_start - 1; + u32 second_len = rdelim_end - mdelim_pos - 1; + u8 scratch[AFL_TXT_STRING_MAX_LEN]; + + memcpy(scratch, ldelim_start + 1, first_len); + + if (first_len != second_len) { + + memmove(ldelim_start + second_len + 1, mdelim_pos, + out_buf_end - mdelim_pos); + + } + + memcpy(ldelim_start + 1, mdelim_pos + 1, second_len); + + if (first_len != second_len) { + + memmove(mdelim_pos + first_len + 1, rdelim_end, + out_buf_end - rdelim_end); + + } + + memcpy(mdelim_pos + 1, scratch, first_len); + + return 1; + + } + + } + + } + + } + + } + + return 0; + +} + +/* replace a string */ + +static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from, + u8 *to) { + + u8 *start = strnstr(*out_buf + pos, from, *temp_len - pos); + + if (start) { + + u32 from_len = strlen(from); + u32 to_len = strlen(to); + + if (from_len != to_len) { + + memmove(start + to_len, start + from_len, + *temp_len - from_len - (start - *out_buf)); + + } + + memcpy(start, to, to_len); + *temp_len = (*temp_len - from_len + to_len); + + return 1; + + } + + return 0; + +} + +/* Returns 1 if a mutant was generated and placed in out_buf, 0 if none + * generated. */ + +static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { + + s32 temp_len; + u32 pos, yes = 0, + mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 1; + u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS); + temp_len = *orig_temp_len; + memcpy(new_buf, *out_buf, temp_len); + + for (u32 i = 0; i < mutations; i++) { + + if (temp_len < AFL_TXT_MIN_LEN) { return 0; } + + pos = rand_below(afl, temp_len - 1); + int choice = rand_below(afl, 72); + switch (choice) { + + case 0: /* Semantic statement deletion */ + yes += string_replace(out_buf, &temp_len, pos, "\n", "#"); + break; + case 1: + yes += string_replace(out_buf, &temp_len, pos, "(", "(!"); + break; + case 2: + yes += string_replace(out_buf, &temp_len, pos, "==", "!="); + break; + case 3: + yes += string_replace(out_buf, &temp_len, pos, "!=", "=="); + break; + case 4: + yes += string_replace(out_buf, &temp_len, pos, "==", "<"); + break; + case 5: + yes += string_replace(out_buf, &temp_len, pos, "<", "=="); + break; + case 6: + yes += string_replace(out_buf, &temp_len, pos, "==", ">"); + break; + case 7: + yes += string_replace(out_buf, &temp_len, pos, ">", "=="); + break; + case 8: + yes += string_replace(out_buf, &temp_len, pos, "=", "<"); + break; + case 9: + yes += string_replace(out_buf, &temp_len, pos, "=", ">"); + break; + case 10: + yes += string_replace(out_buf, &temp_len, pos, "<", ">"); + break; + case 11: + yes += string_replace(out_buf, &temp_len, pos, ">", "<"); + break; + case 12: + yes += string_replace(out_buf, &temp_len, pos, "++", "--"); + break; + case 13: + yes += string_replace(out_buf, &temp_len, pos, "--", "++"); + break; + case 14: + yes += string_replace(out_buf, &temp_len, pos, "+", "-"); + break; + case 15: + yes += string_replace(out_buf, &temp_len, pos, "+", "*"); + break; + case 16: + yes += string_replace(out_buf, &temp_len, pos, "+", "/"); + break; + case 17: + yes += string_replace(out_buf, &temp_len, pos, "+", "%"); + break; + case 18: + yes += string_replace(out_buf, &temp_len, pos, "*", "-"); + break; + case 19: + yes += string_replace(out_buf, &temp_len, pos, "*", "+"); + break; + case 20: + yes += string_replace(out_buf, &temp_len, pos, "*", "/"); + break; + case 21: + yes += string_replace(out_buf, &temp_len, pos, "*", "%"); + break; + case 22: + yes += string_replace(out_buf, &temp_len, pos, "-", "+"); + break; + case 23: + yes += string_replace(out_buf, &temp_len, pos, "-", "*"); + break; + case 24: + yes += string_replace(out_buf, &temp_len, pos, "-", "/"); + break; + case 25: + yes += string_replace(out_buf, &temp_len, pos, "-", "%"); + break; + case 26: + yes += string_replace(out_buf, &temp_len, pos, "/", "-"); + break; + case 27: + yes += string_replace(out_buf, &temp_len, pos, "/", "*"); + break; + case 28: + yes += string_replace(out_buf, &temp_len, pos, "/", "+"); + break; + case 29: + yes += string_replace(out_buf, &temp_len, pos, "/", "%"); + break; + case 30: + yes += string_replace(out_buf, &temp_len, pos, "%", "-"); + break; + case 31: + yes += string_replace(out_buf, &temp_len, pos, "%", "*"); + break; + case 32: + yes += string_replace(out_buf, &temp_len, pos, "%", "/"); + break; + case 33: + yes += string_replace(out_buf, &temp_len, pos, "%", "+"); + break; + case 34: + yes += string_replace(out_buf, &temp_len, pos, " ", "|"); + break; + case 35: + yes += string_replace(out_buf, &temp_len, pos, " ", "$"); + break; + case 36: + yes += string_replace(out_buf, &temp_len, pos, "0", "1"); + break; + case 37: + yes += string_replace(out_buf, &temp_len, pos, "1", "0"); + break; + case 38: + yes += string_replace(out_buf, &temp_len, pos, " ", "`"); + break; + case 39: + yes += string_replace(out_buf, &temp_len, pos, " ", "\""); + break; + case 40: + yes += string_replace(out_buf, &temp_len, pos, ";", " "); + break; + case 41: + yes += string_replace(out_buf, &temp_len, pos, "&&", "||"); + break; + case 42: + yes += string_replace(out_buf, &temp_len, pos, "||", "&&"); + break; + case 43: + yes += string_replace(out_buf, &temp_len, pos, "!", ""); + break; + case 44: + yes += string_replace(out_buf, &temp_len, pos, "==", "="); + break; + case 45: + yes += string_replace(out_buf, &temp_len, pos, "--", ""); + break; + case 46: + yes += string_replace(out_buf, &temp_len, pos, "<<", "<"); + break; + case 47: + yes += string_replace(out_buf, &temp_len, pos, ">>", ">"); + break; + case 48: + yes += string_replace(out_buf, &temp_len, pos, "<", "<<"); + break; + case 49: + yes += string_replace(out_buf, &temp_len, pos, ">", ">>"); + break; + case 50: + yes += string_replace(out_buf, &temp_len, pos, "\"", "'"); + break; + case 51: + yes += string_replace(out_buf, &temp_len, pos, "'", "\""); + break; + case 52: + yes += string_replace(out_buf, &temp_len, pos, "(", "\""); + break; + case 53: /* Remove a semicolon delimited statement after a semicolon */ + yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";"); + break; + case 54: /* Remove a semicolon delimited statement after a left curly + brace */ + yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}"); + break; + case 55: /* Remove a curly brace construct */ + yes += delim_replace(out_buf, &temp_len, pos, "{", "}", ""); + break; + case 56: /* Replace a curly brace construct with an empty one */ + yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}"); + break; + case 57: + yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";"); + break; + case 58: + yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";"); + break; + case 59: /* Swap comma delimited things case 1 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")"); + break; + case 60: /* Swap comma delimited things case 2 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ","); + break; + case 61: /* Swap comma delimited things case 3 */ + yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ","); + break; + case 62: /* Swap comma delimited things case 4 */ + yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")"); + break; + case 63: /* Just delete a line */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", ""); + break; + case 64: /* Delete something like "const" case 1 */ + yes += delim_replace(out_buf, &temp_len, pos, " ", " ", ""); + break; + case 65: /* Delete something like "const" case 2 */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", ""); + break; + case 66: /* Delete something like "const" case 3 */ + yes += delim_replace(out_buf, &temp_len, pos, "(", " ", ""); + break; + case 67: /* Swap space delimited things case 1 */ + yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " "); + break; + case 68: /* Swap space delimited things case 2 */ + yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")"); + break; + case 69: /* Swap space delimited things case 3 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " "); + break; + case 70: /* Swap space delimited things case 4 */ + yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")"); + break; + case 71: /* Duplicate a single line of code */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL); + break; + case 72: /* Duplicate a construct (most often, a non-nested for loop */ + yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL); + break; + + } + + } + + if (yes == 0 || temp_len <= 0) { return 0; } + + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); + *out_buf = new_buf; + *orig_temp_len = temp_len; + + return 1; + +} + /* Take the current entry from the queue, fuzz it for a while. This function is a tad too long... returns 0 if fuzzed successfully, 1 if skipped or bailed out. */ @@ -1854,6 +2303,22 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ + u32 r_max, r; + + if (unlikely(afl->expand_havoc)) { + + /* add expensive havoc cases here, they are activated after a full + cycle without finds happened */ + + r_max = 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0) + + (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0); + + } else { + + r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0); + + } + for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2)); @@ -1896,8 +2361,9 @@ havoc_stage: } - switch (rand_below( - afl, 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) { + retry_havoc: + + switch ((r = rand_below(afl, r_max))) { case 0: @@ -2191,176 +2657,203 @@ havoc_stage: break; } - - case 15: { - /* Overwrite bytes with a randomly selected chunk from another - testcase or insert that chunk. */ + default: - if (afl->queued_paths < 2) break; + if (likely(r <= 16 && (afl->extras_cnt || afl->a_extras_cnt))) { - /* Pick a random queue entry and seek to it. */ + /* Values 15 and 16 can be selected only if there are any extras + present in the dictionaries. */ - u32 tid; - do - tid = rand_below(afl, afl->queued_paths); - while (tid == afl->current_entry); + if (r == 15) { - struct queue_entry* target = afl->queue_buf[tid]; + /* Overwrite bytes with an extra. */ - /* Make sure that the target has a reasonable length. */ + if (!afl->extras_cnt || + (afl->a_extras_cnt && rand_below(afl, 2))) { - while (target && (target->len < 2 || target == afl->queue_cur)) - target = target->next; + /* No user-specified extras or odds in our favor. Let's use an + auto-detected one. */ - if (!target) break; + u32 use_extra = rand_below(afl, afl->a_extras_cnt); + u32 extra_len = afl->a_extras[use_extra].len; + u32 insert_at; - /* Read the testcase into a new buffer. */ + if (extra_len > temp_len) { break; } - fd = open(target->fname, O_RDONLY); + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, + extra_len); - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); } + } else { - u32 new_len = target->len; - u8 * new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len); + /* No auto extras or odds in our favor. Use the dictionary. */ - ck_read(fd, new_buf, new_len, target->fname); + u32 use_extra = rand_below(afl, afl->extras_cnt); + u32 extra_len = afl->extras[use_extra].len; + u32 insert_at; - close(fd); + if (extra_len > temp_len) { break; } - u8 overwrite = 0; - if (temp_len >= 2 && rand_below(afl, 2)) - overwrite = 1; - else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) { - if (temp_len >= 2) overwrite = 1; - else break; - } + insert_at = rand_below(afl, temp_len - extra_len + 1); + memcpy(out_buf + insert_at, afl->extras[use_extra].data, + extra_len); - if (overwrite) { + } - u32 copy_from, copy_to, copy_len; + break; - copy_len = choose_block_len(afl, new_len - 1); - if (copy_len > temp_len) copy_len = temp_len; + } else { // case 16 - copy_from = rand_below(afl, new_len - copy_len + 1); - copy_to = rand_below(afl, temp_len - copy_len + 1); + u32 use_extra, extra_len, + insert_at = rand_below(afl, temp_len + 1); + u8 *ptr; - memmove(out_buf + copy_to, new_buf + copy_from, copy_len); + /* Insert an extra. Do the same dice-rolling stuff as for the + previous case. */ - } else { - - u32 clone_from, clone_to, clone_len; - - clone_len = choose_block_len(afl, new_len); - clone_from = rand_below(afl, new_len - clone_len + 1); - - clone_to = rand_below(afl, temp_len); + if (!afl->extras_cnt || + (afl->a_extras_cnt && rand_below(afl, 2))) { - u8 * temp_buf = - ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len); + use_extra = rand_below(afl, afl->a_extras_cnt); + extra_len = afl->a_extras[use_extra].len; + ptr = afl->a_extras[use_extra].data; - /* Head */ + } else { - memcpy(temp_buf, out_buf, clone_to); + use_extra = rand_below(afl, afl->extras_cnt); + extra_len = afl->extras[use_extra].len; + ptr = afl->extras[use_extra].data; - /* Inserted part */ + } - memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len); + if (temp_len + extra_len >= MAX_FILE) { break; } - /* Tail */ - memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to, - temp_len - clone_to); + out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); - swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); - out_buf = temp_buf; - temp_len += clone_len; - - } + /* Tail */ + memmove(out_buf + insert_at + extra_len, out_buf + insert_at, + temp_len - insert_at); - break; + /* Inserted part */ + memcpy(out_buf + insert_at, ptr, extra_len); - } + temp_len += extra_len; - /* Values 15 and 16 can be selected only if there are any extras - present in the dictionaries. */ + break; - case 16: { + } - /* Overwrite bytes with an extra. */ + } else - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + switch (r) { - /* No user-specified extras or odds in our favor. Let's use an - auto-detected one. */ + case 15: // fall through + case 17: { - u32 use_extra = rand_below(afl, afl->a_extras_cnt); - u32 extra_len = afl->a_extras[use_extra].len; - u32 insert_at; + /* Overwrite bytes with a randomly selected chunk from another + testcase or insert that chunk. */ - if (extra_len > temp_len) { break; } + if (afl->queued_paths < 2) break; - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, - extra_len); + /* Pick a random queue entry and seek to it. */ - } else { + u32 tid; + do + tid = rand_below(afl, afl->queued_paths); + while (tid == afl->current_entry); - /* No auto extras or odds in our favor. Use the dictionary. */ + struct queue_entry *target = afl->queue_buf[tid]; - u32 use_extra = rand_below(afl, afl->extras_cnt); - u32 extra_len = afl->extras[use_extra].len; - u32 insert_at; + /* Make sure that the target has a reasonable length. */ - if (extra_len > temp_len) { break; } + while (target && (target->len < 2 || target == afl->queue_cur)) + target = target->next; - insert_at = rand_below(afl, temp_len - extra_len + 1); - memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len); + if (!target) break; - } + /* Read the testcase into a new buffer. */ - break; + fd = open(target->fname, O_RDONLY); - } + if (unlikely(fd < 0)) { + + PFATAL("Unable to open '%s'", target->fname); - case 17: { + } - u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1); - u8 *ptr; + u32 new_len = target->len; + u8 *new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len); - /* Insert an extra. Do the same dice-rolling stuff as for the - previous case. */ + ck_read(fd, new_buf, new_len, target->fname); - if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) { + close(fd); - use_extra = rand_below(afl, afl->a_extras_cnt); - extra_len = afl->a_extras[use_extra].len; - ptr = afl->a_extras[use_extra].data; + u8 overwrite = 0; + if (temp_len >= 2 && rand_below(afl, 2)) + overwrite = 1; + else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) { - } else { + if (temp_len >= 2) + overwrite = 1; + else + break; - use_extra = rand_below(afl, afl->extras_cnt); - extra_len = afl->extras[use_extra].len; - ptr = afl->extras[use_extra].data; + } - } + if (overwrite) { - if (temp_len + extra_len >= MAX_FILE) { break; } + u32 copy_from, copy_to, copy_len; - out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len); + copy_len = choose_block_len(afl, new_len - 1); + if (copy_len > temp_len) copy_len = temp_len; - /* Tail */ - memmove(out_buf + insert_at + extra_len, out_buf + insert_at, - temp_len - insert_at); + copy_from = rand_below(afl, new_len - copy_len + 1); + copy_to = rand_below(afl, temp_len - copy_len + 1); - /* Inserted part */ - memcpy(out_buf + insert_at, ptr, extra_len); + memmove(out_buf + copy_to, new_buf + copy_from, copy_len); - temp_len += extra_len; + } else { - break; + u32 clone_from, clone_to, clone_len; - } + clone_len = choose_block_len(afl, new_len); + clone_from = rand_below(afl, new_len - clone_len + 1); + + clone_to = rand_below(afl, temp_len); + + u8 *temp_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), + temp_len + clone_len); + + /* Head */ + + memcpy(temp_buf, out_buf, clone_to); + + /* Inserted part */ + + memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len); + + /* Tail */ + memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to, + temp_len - clone_to); + + swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch)); + out_buf = temp_buf; + temp_len += clone_len; + + } + + break; + + } + + default: + + // perform ascii mutations + if (text_mutation(afl, &out_buf, &temp_len) == 0) + goto retry_havoc; + + } // end default: switch(r) } @@ -4827,7 +5320,7 @@ u8 fuzz_one(afl_state_t *afl) { return (key_val_lv_1 | key_val_lv_2); -#undef BUF_PARAMS - } +#undef BUF_PARAMS + diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index a96995e5..56073b0a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -24,6 +24,7 @@ #include "afl-fuzz.h" #include +#include #define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size @@ -102,6 +103,108 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } +/* check if ascii or UTF-8 */ + +static u8 check_if_text(struct queue_entry *q) { + + if (q->len < AFL_TXT_MIN_LEN) return 0; + + u8 buf[MAX_FILE]; + s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp; + + if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; + if ((comp = read(fd, buf, len)) != len) return 0; + close(fd); + + while (offset < len) { + + // ASCII: <= 0x7F to allow ASCII control characters + if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A || + buf[offset + 0] == 0x0D || + (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) { + + offset++; + utf8++; + ascii++; + continue; + + } + + if (isascii((int)buf[offset]) || isprint((int)buf[offset])) { + + ascii++; + // we continue though as it can also be a valid utf8 + + } + + // non-overlong 2-byte + if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) { + + offset += 2; + utf8++; + comp--; + continue; + + } + + // excluding overlongs + if ((buf[offset + 0] == 0xE0 && + (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // straight 3-byte + (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) || + buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // excluding surrogates + (buf[offset + 0] == 0xED && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) { + + offset += 3; + utf8++; + comp -= 2; + continue; + + } + + // planes 1-3 + if ((buf[offset + 0] == 0xF0 && + (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && + buf[offset + 3] <= 0xBF)) || // planes 4-15 + ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16 + (buf[offset + 0] == 0xF4 && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) { + + offset += 4; + utf8++; + comp -= 3; + continue; + + } + + offset++; + + } + + u32 percent_utf8 = (utf8 * 100) / comp; + u32 percent_ascii = (ascii * 100) / len; + + if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT) + return 2; + if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1; + return 0; + +} + /* Append new test case to the queue. */ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { @@ -139,9 +242,10 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { afl->q_prev100 = q; } - - struct queue_entry** queue_buf = ck_maybe_grow(BUF_PARAMS(queue), afl->queued_paths * sizeof(struct queue_entry*)); - queue_buf[afl->queued_paths -1] = q; + + struct queue_entry **queue_buf = ck_maybe_grow( + BUF_PARAMS(queue), afl->queued_paths * sizeof(struct queue_entry *)); + queue_buf[afl->queued_paths - 1] = q; afl->last_path_time = get_cur_time(); @@ -164,6 +268,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } + q->is_ascii = check_if_text(q); + } /* Destroy the entire queue. */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index e56d122a..f68a79e8 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -293,6 +293,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_autoresume = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CYCLE_SCHEDULES", + + afl_environment_variable_len)) { + + afl->cycle_schedules = afl->afl_env.afl_cycle_schedules = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CAL_FAST", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index df2896d2..88f8e902 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1252,11 +1252,42 @@ int main(int argc, char **argv_orig, char **envp) { /* If we had a full queue cycle with no new finds, try recombination strategies next. */ - if (afl->queued_paths == prev_queued) { + if (afl->queued_paths == prev_queued && + (get_cur_time() - afl->start_time) >= 3600) { if (afl->use_splicing) { ++afl->cycles_wo_finds; + switch (afl->expand_havoc) { + + case 0: + afl->expand_havoc = 1; + break; + case 1: + if (afl->limit_time_sig == 0) { + + afl->limit_time_sig = -1; + afl->limit_time_puppet = 0; + + } + + afl->expand_havoc = 2; + break; + case 2: + afl->cycle_schedules = 1; + afl->expand_havoc = 3; + break; + case 3: + // nothing else currently + break; + + } + + if (afl->expand_havoc) { + + } else + + afl->expand_havoc = 1; } else { @@ -1270,6 +1301,53 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->cycle_schedules) { + + /* we cannot mix non-AFLfast schedules with others */ + + switch (afl->schedule) { + + case EXPLORE: + afl->schedule = EXPLOIT; + break; + case EXPLOIT: + afl->schedule = MMOPT; + break; + case MMOPT: + afl->schedule = SEEK; + break; + case SEEK: + afl->schedule = EXPLORE; + break; + case FAST: + afl->schedule = COE; + break; + case COE: + afl->schedule = LIN; + break; + case LIN: + afl->schedule = QUAD; + break; + case QUAD: + afl->schedule = RARE; + break; + case RARE: + afl->schedule = FAST; + break; + + } + + struct queue_entry *q = afl->queue; + // we must recalculate the scores of all queue entries + while (q) { + + update_bitmap_score(afl, q); + q = q->next; + + } + + } + prev_queued = afl->queued_paths; if (afl->sync_id && afl->queue_cycle == 1 && -- cgit 1.4.1 From f32811922ec8f363bdf46a019d984058dbeb06bf Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 29 Jul 2020 11:56:38 +0200 Subject: minor opt --- src/afl-fuzz-one.c | 3 --- src/afl-fuzz-queue.c | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src/afl-fuzz-queue.c') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index a42bb0fc..1f0bf30e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1866,7 +1866,6 @@ havoc_stage: cycle without finds happened */ r_max = 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0); - /* + (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0); */ } else { @@ -1916,8 +1915,6 @@ havoc_stage: } - // retry_havoc: - switch ((r = rand_below(afl, r_max))) { case 0: diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 56073b0a..38e95ac8 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -268,7 +268,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { } - q->is_ascii = check_if_text(q); + /* only redqueen currently uses is_ascii */ + if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q); } -- cgit 1.4.1 From ea9ba53cdbc6d175f3f055c9a308668ebaacda1e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 30 Jul 2020 17:09:22 +0200 Subject: fix oob reads, code-format --- examples/aflpp_driver/aflpp_driver.c | 168 ++++++++++++++++++------------ examples/aflpp_driver/aflpp_driver_test.c | 16 +-- src/afl-fuzz-queue.c | 55 +++++----- src/afl-fuzz-redqueen.c | 3 +- test/test-floatingpoint.c | 8 +- 5 files changed, 146 insertions(+), 104 deletions(-) (limited to 'src/afl-fuzz-queue.c') diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c index eca3dcd1..86c7a69f 100644 --- a/examples/aflpp_driver/aflpp_driver.c +++ b/examples/aflpp_driver/aflpp_driver.c @@ -14,12 +14,15 @@ cat << EOF > test_fuzzer.cc #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > 0 && data[0] == 'H') if (size > 1 && data[1] == 'I') if (size > 2 && data[2] == '!') __builtin_trap(); return 0; + } + EOF # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c @@ -57,46 +60,46 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both. #include "config.h" #ifdef _DEBUG -#include "hash.h" + #include "hash.h" #endif // Platform detection. Copied from FuzzerInternal.h #ifdef __linux__ -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 + #define LIBFUZZER_LINUX 1 + #define LIBFUZZER_APPLE 0 + #define LIBFUZZER_NETBSD 0 + #define LIBFUZZER_FREEBSD 0 + #define LIBFUZZER_OPENBSD 0 #elif __APPLE__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 + #define LIBFUZZER_LINUX 0 + #define LIBFUZZER_APPLE 1 + #define LIBFUZZER_NETBSD 0 + #define LIBFUZZER_FREEBSD 0 + #define LIBFUZZER_OPENBSD 0 #elif __NetBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 + #define LIBFUZZER_LINUX 0 + #define LIBFUZZER_APPLE 0 + #define LIBFUZZER_NETBSD 1 + #define LIBFUZZER_FREEBSD 0 + #define LIBFUZZER_OPENBSD 0 #elif __FreeBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 + #define LIBFUZZER_LINUX 0 + #define LIBFUZZER_APPLE 0 + #define LIBFUZZER_NETBSD 0 + #define LIBFUZZER_FREEBSD 1 + #define LIBFUZZER_OPENBSD 0 #elif __OpenBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 + #define LIBFUZZER_LINUX 0 + #define LIBFUZZER_APPLE 0 + #define LIBFUZZER_NETBSD 0 + #define LIBFUZZER_FREEBSD 0 + #define LIBFUZZER_OPENBSD 1 #else -#error "Support for your platform has not been implemented" + #error "Support for your platform has not been implemented" #endif -int __afl_sharedmem_fuzzing = 1; -extern unsigned int *__afl_fuzz_len; +int __afl_sharedmem_fuzzing = 1; +extern unsigned int * __afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; // libFuzzer interface is thin, so we don't include any libFuzzer headers. @@ -105,11 +108,11 @@ __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); // Notify AFL about persistent mode. static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -int __afl_persistent_loop(unsigned int); +int __afl_persistent_loop(unsigned int); // Notify AFL about deferred forkserver. static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -void __afl_manual_init(); +void __afl_manual_init(); // Use this optionally defined function to output sanitizer messages even if // user asks to close stderr. @@ -122,98 +125,121 @@ static FILE *output_file; // Experimental feature to use afl_driver without AFL's deferred mode. // Needs to run before __afl_auto_init. __attribute__((constructor(0))) static void __decide_deferred_forkserver(void) { + if (getenv("AFL_DRIVER_DONT_DEFER")) { + if (unsetenv("__AFL_DEFER_FORKSRV")) { + perror("Failed to unset __AFL_DEFER_FORKSRV"); abort(); + } + } + } // If the user asks us to duplicate stderr, then do it. static void maybe_duplicate_stderr() { + char *stderr_duplicate_filename = getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - if (!stderr_duplicate_filename) - return; + if (!stderr_duplicate_filename) return; FILE *stderr_duplicate_stream = freopen(stderr_duplicate_filename, "a+", stderr); if (!stderr_duplicate_stream) { + fprintf( stderr, "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); abort(); + } + output_file = stderr_duplicate_stream; + } // Most of these I/O functions were inspired by/copied from libFuzzer's code. static void discard_output(int fd) { + FILE *temp = fopen("/dev/null", "w"); - if (!temp) - abort(); + if (!temp) abort(); dup2(fileno(temp), fd); fclose(temp); + } -static void close_stdout() { discard_output(STDOUT_FILENO); } +static void close_stdout() { + + discard_output(STDOUT_FILENO); + +} // Prevent the targeted code from writing to "stderr" but allow sanitizers and // this driver to do so. static void dup_and_close_stderr() { + int output_fileno = fileno(output_file); int output_fd = dup(output_fileno); - if (output_fd <= 0) - abort(); + if (output_fd <= 0) abort(); FILE *new_output_file = fdopen(output_fd, "w"); - if (!new_output_file) - abort(); - if (!__sanitizer_set_report_fd) - return; - __sanitizer_set_report_fd((void*)output_fd); + if (!new_output_file) abort(); + if (!__sanitizer_set_report_fd) return; + __sanitizer_set_report_fd((void *)output_fd); discard_output(output_fileno); + } // Close stdout and/or stderr if user asks for it. static void maybe_close_fd_mask() { + char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK"); - if (!fd_mask_str) - return; + if (!fd_mask_str) return; int fd_mask = atoi(fd_mask_str); - if (fd_mask & 2) - dup_and_close_stderr(); - if (fd_mask & 1) - close_stdout(); + if (fd_mask & 2) dup_and_close_stderr(); + if (fd_mask & 1) close_stdout(); + } // Define LLVMFuzzerMutate to avoid link failures for targets that use it // with libFuzzer's LLVMFuzzerCustomMutator. size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - //assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); + + // assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); return 0; + } // Execute any files provided as parameters. static int ExecuteFilesOnyByOne(int argc, char **argv) { + unsigned char *buf = malloc(MAX_FILE); for (int i = 1; i < argc; i++) { + int fd = open(argv[i], O_RDONLY); if (fd == -1) continue; ssize_t length = read(fd, buf, MAX_FILE); if (length > 0) { + printf("Reading %zu bytes from %s\n", length, argv[i]); LLVMFuzzerTestOneInput(buf, length); printf("Execution successful.\n"); + } + } + free(buf); return 0; + } int main(int argc, char **argv) { + printf( "======================= INFO =========================\n" "This binary is built for AFL-fuzz.\n" @@ -226,36 +252,39 @@ int main(int argc, char **argv) { "afl-fuzz will run N iterations before " "re-spawning the process (default: 1000)\n" "======================================================\n", - argv[0], argv[0], argv[0]); + argv[0], argv[0], argv[0]); output_file = stderr; maybe_duplicate_stderr(); maybe_close_fd_mask(); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); + if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv); // Do any other expensive one-time initialization here. uint8_t dummy_input[64] = {0}; - memcpy(dummy_input, (void*)AFL_PERSISTENT, sizeof(AFL_PERSISTENT)); - memcpy(dummy_input + 32, (void*)AFL_DEFER_FORKSVR, sizeof(AFL_DEFER_FORKSVR)); + memcpy(dummy_input, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT)); + memcpy(dummy_input + 32, (void *)AFL_DEFER_FORKSVR, + sizeof(AFL_DEFER_FORKSVR)); int N = INT_MAX; if (argc == 2 && argv[1][0] == '-') - N = atoi(argv[1] + 1); - else if(argc == 2 && (N = atoi(argv[1])) > 0) - printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); + N = atoi(argv[1] + 1); + else if (argc == 2 && (N = atoi(argv[1])) > 0) + printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N); else if (argc > 1) { -// if (!getenv("AFL_DRIVER_DONT_DEFER")) { - __afl_sharedmem_fuzzing = 0; - __afl_manual_init(); -// } + + // if (!getenv("AFL_DRIVER_DONT_DEFER")) { + + __afl_sharedmem_fuzzing = 0; + __afl_manual_init(); + // } return ExecuteFilesOnyByOne(argc, argv); exit(0); + } assert(N > 0); -// if (!getenv("AFL_DRIVER_DONT_DEFER")) + // if (!getenv("AFL_DRIVER_DONT_DEFER")) __afl_manual_init(); // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization @@ -264,17 +293,26 @@ int main(int argc, char **argv) { int num_runs = 0; while (__afl_persistent_loop(N)) { + #ifdef _DEBUG - fprintf(stderr, "CLIENT crc: %016llx len: %u\n", hash64(__afl_fuzz_ptr, *__afl_fuzz_len, 0xa5b35705), *__afl_fuzz_len); + fprintf(stderr, "CLIENT crc: %016llx len: %u\n", + hash64(__afl_fuzz_ptr, *__afl_fuzz_len, 0xa5b35705), + *__afl_fuzz_len); fprintf(stderr, "RECV:"); for (int i = 0; i < *__afl_fuzz_len; i++) fprintf(stderr, "%02x", __afl_fuzz_ptr[i]); - fprintf(stderr,"\n"); + fprintf(stderr, "\n"); #endif if (*__afl_fuzz_len) { + num_runs++; LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len); + } + } + printf("%s: successfully executed %d input(s)\n", argv[0], num_runs); + } + diff --git a/examples/aflpp_driver/aflpp_driver_test.c b/examples/aflpp_driver/aflpp_driver_test.c index 83278f5c..e4567bbf 100644 --- a/examples/aflpp_driver/aflpp_driver_test.c +++ b/examples/aflpp_driver/aflpp_driver_test.c @@ -6,18 +6,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - fprintf(stderr, "FUNC crc: %016llx len: %lu\n", hash64((u8*)Data, (unsigned int) Size, (unsigned long long int) 0xa5b35705), Size); - - if (Size < 5) - return 0; + fprintf(stderr, "FUNC crc: %016llx len: %lu\n", + hash64((u8 *)Data, (unsigned int)Size, + (unsigned long long int)0xa5b35705), + Size); + + if (Size < 5) return 0; if (Data[0] == 'F') if (Data[1] == 'A') if (Data[2] == '$') if (Data[3] == '$') - if (Data[4] == '$') - abort(); - + if (Data[4] == '$') abort(); + return 0; } + diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 38e95ac8..71874283 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -139,7 +139,8 @@ static u8 check_if_text(struct queue_entry *q) { // non-overlong 2-byte if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) { + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF)) && + len - offset > 1) { offset += 2; utf8++; @@ -149,18 +150,19 @@ static u8 check_if_text(struct queue_entry *q) { } // excluding overlongs - if ((buf[offset + 0] == 0xE0 && - (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && - buf[offset + 2] <= 0xBF)) || // straight 3-byte - (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) || - buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && - buf[offset + 2] <= 0xBF)) || // excluding surrogates - (buf[offset + 0] == 0xED && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) { + if ((len - offset > 2) && + ((buf[offset + 0] == 0xE0 && + (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // straight 3-byte + (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) || + buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && + buf[offset + 2] <= 0xBF)) || // excluding surrogates + (buf[offset + 0] == 0xED && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF)))) { offset += 3; utf8++; @@ -170,19 +172,20 @@ static u8 check_if_text(struct queue_entry *q) { } // planes 1-3 - if ((buf[offset + 0] == 0xF0 && - (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && - buf[offset + 3] <= 0xBF)) || // planes 4-15 - ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16 - (buf[offset + 0] == 0xF4 && - (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) && - (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && - (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) { + if ((len - offset > 3) && + ((buf[offset + 0] == 0xF0 && + (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && + buf[offset + 3] <= 0xBF)) || // planes 4-15 + ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16 + (buf[offset + 0] == 0xF4 && + (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) && + (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) && + (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)))) { offset += 4; utf8++; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 57e60c3d..a2e8f992 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -269,8 +269,7 @@ static long long strntoll(const char *str, size_t sz, char **end, int base) { long long ret; const char *beg = str; - for (; beg && sz && *beg == ' '; beg++, sz--) - ; + for (; beg && sz && *beg == ' '; beg++, sz--) {}; if (!sz || sz >= sizeof(buf)) { diff --git a/test/test-floatingpoint.c b/test/test-floatingpoint.c index d1709b90..3a699595 100644 --- a/test/test-floatingpoint.c +++ b/test/test-floatingpoint.c @@ -17,10 +17,10 @@ int main(void) { int len = __AFL_FUZZ_TESTCASE_LEN; if (len != sizeof(float)) return 1; - /* 15 + 1/2 = 15.5 */ - /* 15 + 1/2 + 1/8 = 15.625 */ - /* 15 + 1/2 + 1/8 + 1/32 = 15.65625 */ - /* 15 + 1/2 + 1/8 + 1/32 + 1/128 = 15.6640625 */ + /* 15 + 1/2 = 15.5 */ + /* 15 + 1/2 + 1/8 = 15.625 */ + /* 15 + 1/2 + 1/8 + 1/32 = 15.65625 */ + /* 15 + 1/2 + 1/8 + 1/32 + 1/128 = 15.6640625 */ if ((-*magic == 15.0 + 0.5 + 0.125 + 0.03125 + 0.0078125)) abort(); } -- cgit 1.4.1