add AFL_NO_STARTUP_CALIBRATION feature
MODIFY
docs/Changelog.md
docs/Changelog.md
@@ -9,7 +9,14 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++4.03a (dev)
- - ... your PR? :)
+ - afl-fuzz:
+ - added AFL_NO_STARTUP_CALIBRATION to start fuzzing at once instead
+ of calibrating all initial seeds first. Good for large queues
+ and long execution times, especially in CIs.
+ - qemu_mode:
+ - added AFL_QEMU_TRACK_UNSTABLE to log the addresses of unstable
+ edges (together with AFL_DEBUG=1 afl-fuzz). thanks to
+ worksbutnottested!
### Version ++4.02c (release)

MODIFY
docs/env_variables.md
docs/env_variables.md
@@ -462,6 +462,9 @@ checks or alter some of the more exotic semantics of the tool:
some basic stats. This behavior is also automatically triggered when the
output from afl-fuzz is redirected to a file or to a pipe.
+ - Setting `AFL_NO_STARTUP_CALIBRATION` will skip the initial calibration
+ of all starting seeds, and start fuzzing at once.
+
- In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for
afl-qemu-trace and afl-frida-trace.so.

MODIFY
docs/fuzzing_in_depth.md
docs/fuzzing_in_depth.md
@@ -626,6 +626,9 @@ from other fuzzers in the campaign first.
If you have a large corpus, a corpus from a previous run or are fuzzing in a CI,
then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.
+If the queue in the CI is huge and/or the execution time is slow then you can
+also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration
+phase and start fuzzing at once.
You can also use different fuzzers. If you are using AFL spinoffs or AFL
conforming fuzzers, then just use the same -o directory and give it a unique
@@ -902,6 +905,10 @@ complex file formats.
Some notes on continuous integration (CI) fuzzing - this fuzzing is different to
normal fuzzing campaigns as these are much shorter runnings.
+If the queue in the CI is huge and/or the execution time is slow then you can
+also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration
+phase and start fuzzing at once.
+
1. Always:
* LTO has a much longer compile time which is diametrical to short fuzzing -
hence use afl-clang-fast instead.

MODIFY
include/afl-fuzz.h
include/afl-fuzz.h
@@ -386,7 +386,8 @@ typedef struct afl_env_vars {
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
- afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme;
+ afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme,
+ afl_no_startup_calibration;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@@ -1122,6 +1123,7 @@ void bind_to_free_cpu(afl_state_t *);
void setup_post(afl_state_t *);
void read_testcases(afl_state_t *, u8 *);
void perform_dry_run(afl_state_t *);
+void no_dry_run(afl_state_t *);
void pivot_inputs(afl_state_t *);
u32 find_start_position(afl_state_t *);
void find_timeout(afl_state_t *);

MODIFY
include/envs.h
include/envs.h
@@ -165,6 +165,7 @@ static char *afl_environment_variables[] = {
"AFL_NO_FORKSRV",
"AFL_NO_UI",
"AFL_NO_PYTHON",
+ "AFL_NO_STARTUP_CALIBRATION",
"AFL_UNTRACER_FILE",
"AFL_LLVM_USE_TRACE_PC",
"AFL_MAP_SIZE",

MODIFY
src/afl-fuzz-init.c
src/afl-fuzz-init.c
@@ -850,6 +850,30 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
+/* In case no initial calibration is to be performed (e.g. huge queue and slow
+execution time), then setting AFL_NO_STARTUP_CALIBRATION will help getting
+initial data. For this to succeed, non-calibrated corpus entries have to look
+especially juicy so they are more likely to be selected then a calibrated good
+looking one. */
+
+void no_dry_run(afl_state_t *afl) {
+
+ struct queue_entry *q;
+ u32 idx;
+
+ for (idx = 0; idx < afl->queued_items; idx++) {
+
+ q = afl->queue_buf[idx];
+ if (unlikely(!q || q->disabled)) { continue; }
+
+ q->exec_us = 1;
+ q->bitmap_size = MAP_SIZE;
+ q->tc_ref = MAP_SIZE;
+
+ }
+
+}
+
/* Perform dry run of all test cases to confirm that the app is working as
expected. This is done only for the initial inputs, and only once. */

MODIFY
src/afl-fuzz-queue.c
src/afl-fuzz-queue.c
@@ -795,8 +795,14 @@ void cull_queue(afl_state_t *afl) {
u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
- u32 avg_exec_us = afl->total_cal_us / afl->total_cal_cycles;
- u32 avg_bitmap_size = afl->total_bitmap_size / afl->total_bitmap_entries;
+ u32 cal_cycles = afl->total_cal_cycles;
+ u32 bitmap_entries = afl->total_bitmap_entries;
+
+ if (unlikely(!cal_cycles)) { cal_cycles = 1; }
+ if (unlikely(!bitmap_entries)) { bitmap_entries = 1; }
+
+ u32 avg_exec_us = afl->total_cal_us / cal_cycles;
+ u32 avg_bitmap_size = afl->total_bitmap_size / bitmap_entries;
u32 perf_score = 100;
/* Adjust score based on execution speed of this path, compared to the

MODIFY
src/afl-fuzz-state.c
src/afl-fuzz-state.c
@@ -265,6 +265,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_cmplog_only_new =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_no_startup_calibration =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_NO_UI", afl_environment_variable_len)) {
afl->afl_env.afl_no_ui =

MODIFY
src/afl-fuzz.c
src/afl-fuzz.c
@@ -273,6 +273,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
+ "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n"
"AFL_NO_UI: switch status screen off\n"
DYN_COLOR
@@ -2150,8 +2151,18 @@ int main(int argc, char **argv_orig, char **envp) {
memset(afl->virgin_tmout, 255, map_size);
memset(afl->virgin_crash, 255, map_size);
+ if (likely(!afl->afl_env.afl_no_startup_calibration)) {
+
perform_dry_run(afl);
+ } else {
+
+ ACTF("skipping initial seed calibration due option override");
+ usleep(1000);
+ no_dry_run(afl);
+
+ }
+
if (afl->q_testcase_max_cache_entries) {
afl->q_testcase_cache =

add AFL_NO_STARTUP_CALIBRATION feature