From e64c3f86532f6528f3ca0db28c15e002a9b1c491 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 3 Mar 2025 18:03:59 +0100 Subject: [PATCH 01/61] code format --- frida_mode/src/asan/asan.c | 16 ++++++++-------- frida_mode/src/lib/lib.c | 18 ++++++++++-------- frida_mode/src/lib/lib_apple.c | 22 ++++++++++++---------- frida_mode/src/prefetch.c | 2 ++ frida_mode/src/ranges.c | 11 +++++++---- src/afl-cc.c | 2 ++ 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index 66ff7eac..e89c0d62 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -28,11 +28,10 @@ void asan_init(void) { } #ifdef GUM_16_6_PLUS -static gboolean asan_exclude_module(GumModule *module, - gpointer user_data) { +static gboolean asan_exclude_module(GumModule *module, gpointer user_data) { - gchar *symbol_name = (gchar *)user_data; - GumAddress address; + gchar *symbol_name = (gchar *)user_data; + GumAddress address; const GumMemoryRange *range = gum_module_get_range(module); address = gum_module_find_export_by_name(module, symbol_name); @@ -41,14 +40,13 @@ static gboolean asan_exclude_module(GumModule *module, /* If the reported address of the symbol is outside of the range of the module * then ignore it */ if (address < range->base_address) { return TRUE; } - if (address > (range->base_address + range->size)) { - return TRUE; - } + if (address > (range->base_address + range->size)) { return TRUE; } - ranges_add_exclude((GumMemoryRange *) range); + ranges_add_exclude((GumMemoryRange *)range); return FALSE; } + #else static gboolean asan_exclude_module(const GumModuleDetails *details, gpointer user_data) { @@ -72,6 +70,7 @@ static gboolean asan_exclude_module(const GumModuleDetails *details, return FALSE; } + #endif void asan_exclude_module_by_symbol(gchar *symbol_name) { @@ -79,3 +78,4 @@ void asan_exclude_module_by_symbol(gchar *symbol_name) { gum_process_enumerate_modules(asan_exclude_module, symbol_name); } + diff --git a/frida_mode/src/lib/lib.c b/frida_mode/src/lib/lib.c index f774333d..c5a1e16e 100644 --- a/frida_mode/src/lib/lib.c +++ b/frida_mode/src/lib/lib.c @@ -39,13 +39,12 @@ typedef struct { static guint64 text_base = 0; static guint64 text_limit = 0; -#ifdef GUM_16_6_PLUS -static gboolean lib_find_exe(GumModule *module, - gpointer user_data) { + #ifdef GUM_16_6_PLUS +static gboolean lib_find_exe(GumModule *module, gpointer user_data) { - lib_details_t *lib_details = (lib_details_t *)user_data; - const gchar *name = gum_module_get_name(module); - const gchar *path = gum_module_get_path(module); + lib_details_t *lib_details = (lib_details_t *)user_data; + const gchar *name = gum_module_get_name(module); + const gchar *path = gum_module_get_path(module); const GumMemoryRange *range = gum_module_get_range(module); strncpy(lib_details->name, name, PATH_MAX); @@ -57,7 +56,8 @@ static gboolean lib_find_exe(GumModule *module, return FALSE; } -#else + + #else static gboolean lib_find_exe(const GumModuleDetails *details, gpointer user_data) { @@ -72,7 +72,8 @@ static gboolean lib_find_exe(const GumModuleDetails *details, return FALSE; } -#endif + + #endif static void lib_validate_hdr(Elf_Ehdr *hdr) { @@ -210,3 +211,4 @@ guint64 lib_get_text_limit(void) { } #endif + diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c index 5046c34f..6498f674 100644 --- a/frida_mode/src/lib/lib_apple.c +++ b/frida_mode/src/lib/lib_apple.c @@ -12,16 +12,15 @@ extern void gum_darwin_enumerate_modules(mach_port_t task, static guint64 text_base = 0; static guint64 text_limit = 0; -#ifdef GUM_16_6_PLUS -static gboolean lib_get_main_module(GumModule *module, - gpointer user_data) { + #ifdef GUM_16_6_PLUS +static gboolean lib_get_main_module(GumModule *module, gpointer user_data) { - GumDarwinModule **ret = (GumDarwinModule **)user_data; - const gchar *path = gum_module_get_path(module); + GumDarwinModule **ret = (GumDarwinModule **)user_data; + const gchar *path = gum_module_get_path(module); const GumMemoryRange *range = gum_module_get_range(module); - GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory( - path, mach_task_self(), range->base_address, - GUM_DARWIN_MODULE_FLAGS_NONE, NULL); + GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory( + path, mach_task_self(), range->base_address, GUM_DARWIN_MODULE_FLAGS_NONE, + NULL); FVERBOSE("Found main module: %s", darwin_module->name); @@ -30,7 +29,8 @@ static gboolean lib_get_main_module(GumModule *module, return FALSE; } -#else + + #else static gboolean lib_get_main_module(const GumModuleDetails *details, gpointer user_data) { @@ -46,7 +46,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details, return FALSE; } -#endif + + #endif gboolean lib_get_text_section(const GumDarwinSectionDetails *details, gpointer user_data) { @@ -105,3 +106,4 @@ guint64 lib_get_text_limit(void) { } #endif + diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 74291859..9d14fb6e 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -262,6 +262,7 @@ static int prefetch_on_fork(void) { } static void prefetch_hook_fork(void) { + #ifdef GUM_16_6_PLUS void *fork_addr = GSIZE_TO_POINTER(gum_module_find_global_export_by_name("fork")); @@ -305,3 +306,4 @@ void prefetch_init(void) { iface->notify_backpatch = gum_afl_stalker_backpatcher_notify; } + diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index b2df1930..d238eb10 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -118,9 +118,9 @@ static void convert_address_token(gchar *token, GumMemoryRange *range) { #ifdef GUM_16_6_PLUS static gboolean convert_name_token_for_module(GumModule *module, - gpointer user_data) { + gpointer user_data) { - convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data; + convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data; const GumMemoryRange *range = gum_module_get_range(module); const gchar *path = gum_module_get_path(module); if (path == NULL) { return true; }; @@ -129,14 +129,15 @@ static gboolean convert_name_token_for_module(GumModule *module, FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "x %s", - ctx->suffix, range->base_address, - range->base_address + range->size, path); + ctx->suffix, range->base_address, range->base_address + range->size, + path); *ctx->range = *range; ctx->done = true; return false; } + #else static gboolean convert_name_token_for_module(const GumModuleDetails *details, gpointer user_data) { @@ -156,6 +157,7 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details, return false; } + #endif static void convert_name_token(gchar *token, GumMemoryRange *range) { @@ -736,3 +738,4 @@ void ranges_exclude() { } } + diff --git a/src/afl-cc.c b/src/afl-cc.c index 12a361a8..f95216a6 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2033,8 +2033,10 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) { + insert_param(aflcc, "-fsanitize=realtime"); aflcc->have_rtsan = 1; + } if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { From 8b543df04c96035ebf6ddd0c9807961343304174 Mon Sep 17 00:00:00 2001 From: Evian-Zhang Date: Wed, 5 Mar 2025 18:51:37 +0800 Subject: [PATCH 02/61] Add notes about cpu bind in docker --- docs/fuzzing_in_depth.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 5e5b8629..11773eb7 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -496,6 +496,8 @@ Note: protection against attacks! So set strong firewall rules and only expose SSH as a network service if you use these (which is highly recommended). +If you execute afl-fuzz in a Docker container, it is recommended to pass [`--cpuset-cpus`](https://docs.docker.com/engine/containers/resource_constraints/#configure-the-default-cfs-scheduler) option with free CPU cores to docker daemon when starting the container, or pass `AFL_NO_AFFINITY` to afl-fuzz. This is due to the fact that AFL++ will bind to a free CPU core by default, while Docker container will prevent AFL++ instance from seeing processes in other containers or host, which leads to all AFL++ instances trying to bind the same CPU core. + If you have an input corpus from [step 2](#2-preparing-the-fuzzing-campaign), then specify this directory with the `-i` option. Otherwise, create a new directory and create a file with any content as test data in there. From 78952e84407bb14e0a030d6ec8b4075e70582949 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 6 Mar 2025 14:15:53 +0100 Subject: [PATCH 03/61] ensure constants are kept for LLVMFuzzerTestOneInput --- utils/aflpp_driver/aflpp_driver.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 6cf62dab..0c56c816 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -106,12 +106,16 @@ __attribute__((weak)) void __asan_unpoison_memory_region( __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size); // Notify AFL about persistent mode. -static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -int __afl_persistent_loop(unsigned int); +__attribute__((section(".rodata"), used, + retain)) static const char AFL_PERSISTENT[] = + "##SIG_AFL_PERSISTENT##"; +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(); +__attribute__((section(".rodata"), used, + retain)) static const char AFL_DEFER_FORKSVR[] = + "##SIG_AFL_DEFER_FORKSRV##"; +void __afl_manual_init(); // Use this optionally defined function to output sanitizer messages even if // user asks to close stderr. @@ -350,11 +354,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( // 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)); - int N = INT_MAX; if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) { From f27f109880fe5752610be7face086523e5fd9026 Mon Sep 17 00:00:00 2001 From: Yuvraj Saxena Date: Mon, 10 Mar 2025 17:43:18 +0530 Subject: [PATCH 04/61] fix(afl-fuzz-init): ensure proper permissions for setting CPU governor The previous command used tee without sudo, which could fail due to insufficient permissions. Signed-off-by: Yuvraj Saxena --- src/afl-fuzz-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index a89c256b..d8e7169d 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2601,7 +2601,7 @@ void check_cpu_governor(afl_state_t *afl) { " afl-fuzz. To keep things moving, run these commands as root:\n\n" " cd /sys/devices/system/cpu\n" - " echo performance | tee cpu*/cpufreq/scaling_governor\n\n" + " echo performance | sudo tee cpu*/cpufreq/scaling_governor\n\n" " You can later go back to the original state by replacing " "'performance'\n" From 4cabb81996222da3df87b21bf433ca927d965031 Mon Sep 17 00:00:00 2001 From: Andy Knowles Date: Mon, 24 Mar 2025 16:30:05 +0100 Subject: [PATCH 05/61] Better handling of exit codes used by sanitzers --- docs/fuzzing_in_depth.md | 6 ++++ include/forkserver.h | 4 ++- src/afl-forkserver.c | 20 +++++++----- src/afl-fuzz-init.c | 67 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 11773eb7..fea9ca0b 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -247,6 +247,12 @@ CFISAN. You might need to experiment which sanitizers you can combine in a target (which means more instances can be run without a sanitized target, which is more effective). +Note that some sanitizers (MSAN and LSAN) exit with a particular exit code +instead of aborting. afl-fuzz treats these exit codes as a crash when these +sanitizers are enabled. If the target uses these exit codes there could be false +positives among the saved crashes. LSAN uses exit code 23 and MSAN uses exit +code 86. + ### d) Modifying the target If the target has features that make fuzzing more difficult, e.g., checksums, diff --git a/include/forkserver.h b/include/forkserver.h index caea1848..4f574aa1 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -137,6 +137,8 @@ typedef struct afl_forkserver { u8 last_kill_signal; /* Signal that killed the child */ + u8 last_exit_code; /* Child exit code if counted as a crash */ + bool use_shmem_fuzz; /* use shared mem for test cases */ bool support_shmem_fuzz; /* set by afl-fuzz */ @@ -155,7 +157,7 @@ typedef struct afl_forkserver { bool no_unlink; /* do not unlink cur_input */ - bool uses_asan; /* Target uses ASAN? */ + u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */ bool debug; /* debug mode? */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 328f818d..3fc86b3b 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -258,7 +258,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->last_run_timed_out = false; fsrv->debug = false; fsrv->uses_crash_exitcode = false; - fsrv->uses_asan = false; + fsrv->uses_asan = 0; #ifdef __AFL_CODE_COVERAGE fsrv->persistent_trace_bits = NULL; @@ -2087,17 +2087,19 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target( /* Did we crash? In a normal case, (abort) WIFSIGNALED(child_status) will be set. - MSAN in uses_asan mode uses a special exit code as it doesn't support + MSAN & LSAN in uses_asan mode use special exit codes as they doesn't support abort_on_error. On top, a user may specify a custom AFL_CRASH_EXITCODE. - Handle all three cases here. */ + Handle all four cases here. */ if (unlikely( /* A normal crash/abort */ (WIFSIGNALED(fsrv->child_status)) || - /* special handling for msan and lsan */ - (fsrv->uses_asan && - (WEXITSTATUS(fsrv->child_status) == MSAN_ERROR || - WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) || + /* special handling for msan */ + ((fsrv->uses_asan & 4) && + WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) || + /* special handling for lsan */ + ((fsrv->uses_asan & 2) && + WEXITSTATUS(fsrv->child_status) == LSAN_ERROR) || /* the custom crash_exitcode was returned by the target */ (fsrv->uses_crash_exitcode && WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) { @@ -2106,6 +2108,10 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target( fsrv->last_kill_signal = WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; + /* For a special exit code, set last_exit_code to non-zero */ + fsrv->last_exit_code = + WIFSIGNALED(fsrv->child_status) ? 0 : WEXITSTATUS(fsrv->child_status); + #ifdef AFL_PERSISTENT_RECORD if (unlikely(fsrv->persistent_record)) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d8e7169d..123fed1d 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1042,6 +1042,47 @@ void perform_dry_run(afl_state_t *afl) { if (afl->crash_mode) { break; } + const u8 *msg_exit_code = ""; + + if (afl->fsrv.uses_asan && !afl->fsrv.last_kill_signal) { + + if ((afl->fsrv.uses_asan & 4) && + afl->fsrv.last_exit_code == MSAN_ERROR) { + + msg_exit_code = + " - The test case terminated with the exit code that is " + "used by MSAN to\n" + " indicate an error. This is counted as a crash by " + "afl-fuzz because you\n" + " have compiled the target with MSAN enabled. This could " + "be a false\n" + " positive if the program returns this exit code under " + "normal operation.\n" + " In that case, either disable MSAN or change the test " + "case or program\n" + " to avoid generating this exit code.\n\n"; + + } else if ((afl->fsrv.uses_asan & 2) && + + afl->fsrv.last_exit_code == LSAN_ERROR) { + + msg_exit_code = + " - The test case terminated with the exit code that is " + "used by LSAN to\n" + " indicate an error. This is counted as a crash by " + "afl-fuzz because you\n" + " have compiled the target with LSAN enabled. This could " + "be a false\n" + " positive if the program returns this exit code under " + "normal operation.\n" + " In that case, either disable LSAN or change the test " + "case or program\n" + " to avoid generating this exit code.\n\n"; + + } + + } + if (afl->fsrv.mem_limit) { u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; @@ -1056,6 +1097,7 @@ void perform_dry_run(afl_state_t *afl) { " so, please remove it. The fuzzer should be seeded with " "interesting\n" " inputs - but not ones that cause an outright crash.\n\n" + "%s" " - The current memory limit (%s) is too low for this " "program, causing\n" @@ -1085,6 +1127,7 @@ void perform_dry_run(afl_state_t *afl) { "other options\n" " fail, poke the Awesome Fuzzing Discord for " "troubleshooting tips.\n", + msg_exit_code, stringify_mem_size(val_buf, sizeof(val_buf), afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit - 1); @@ -1101,6 +1144,7 @@ void perform_dry_run(afl_state_t *afl) { " so, please remove it. The fuzzer should be seeded with " "interesting\n" " inputs - but not ones that cause an outright crash.\n\n" + "%s" " - In QEMU persistent mode the selected address(es) for the " "loop are not\n" @@ -1113,7 +1157,8 @@ void perform_dry_run(afl_state_t *afl) { " - Least likely, there is a horrible bug in the fuzzer. If " "other options\n" " fail, poke the Awesome Fuzzing Discord for " - "troubleshooting tips.\n"); + "troubleshooting tips.\n", + msg_exit_code); } @@ -3118,11 +3163,23 @@ void check_binary(afl_state_t *afl, u8 *fname) { } - if (afl_memmem(f_data, f_len, "__asan_init", 11) || - afl_memmem(f_data, f_len, "__msan_init", 11) || - afl_memmem(f_data, f_len, "__lsan_init", 11)) { + afl->fsrv.uses_asan = 0; - afl->fsrv.uses_asan = 1; + if (afl_memmem(f_data, f_len, "__asan_init", 11)) { + + afl->fsrv.uses_asan |= 1; + + } + + if (afl_memmem(f_data, f_len, "__lsan_init", 11)) { + + afl->fsrv.uses_asan |= 2; + + } + + if (afl_memmem(f_data, f_len, "__msan_init", 11)) { + + afl->fsrv.uses_asan |= 4; } From f27c504f293b3106ae827bf7b6124e192445d2c8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 25 Mar 2025 20:57:29 +0100 Subject: [PATCH 06/61] update afl-*-config --- afl-persistent-config | 3 ++- afl-system-config | 3 ++- docs/Changelog.md | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/afl-persistent-config b/afl-persistent-config index dede032f..da67bf16 100755 --- a/afl-persistent-config +++ b/afl-persistent-config @@ -121,6 +121,7 @@ kernel.sched_child_runs_first=1 kernel.sched_autogroup_enabled=1 kernel.sched_migration_cost_ns=50000000 kernel.sched_latency_ns=250000000 +vm.swappiness=10 EOF } @@ -129,7 +130,7 @@ EOF if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then echo "Configuring performance boot options" LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'` - OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off" + OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off" echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\" sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub fi diff --git a/afl-system-config b/afl-system-config index 7e2cb688..5a194412 100755 --- a/afl-system-config +++ b/afl-system-config @@ -41,6 +41,7 @@ if [ "$PLATFORM" = "Linux" ] ; then sysctl -w kernel.sched_autogroup_enabled=1 sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null sysctl -w kernel.sched_latency_ns=250000000 2>/dev/null + sysctl -w vm.swappiness=10 2>/dev/null echo never > /sys/kernel/mm/transparent_hugepage/enabled test -e /sys/devices/system/cpu/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/scaling_governor test -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor @@ -54,7 +55,7 @@ if [ "$PLATFORM" = "Linux" ] ; then echo dmesg | grep -E -q 'noibrs pcid nopti' || { echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this: - echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"' + echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"' echo } echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed. diff --git a/docs/Changelog.md b/docs/Changelog.md index 1802b355..17d8c08a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -6,6 +6,7 @@ ### Version ++4.32a (dev) - Fixed a bug where after a fast restart of a full fuzzed corpus afl-fuzz terminates with "need at least one valid input seed that does not crash" + - Small improvements to afl-*-config ### Version ++4.31c (release) From 6457e2ea30ef21ae018d2a183e88032d31b9cb8c Mon Sep 17 00:00:00 2001 From: r3sting Date: Sat, 29 Mar 2025 16:12:29 -0700 Subject: [PATCH 07/61] Fix frida-mode compliation error for MacOS --- frida_mode/GNUmakefile | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 545cde4f..4ee2b40a 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -190,12 +190,25 @@ GUM_DEVKIT_VERSION=16.1.11 GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)" -IS_GUM_16_6_PLUS := $(shell VERSION="$(GUM_DEVKIT_VERSION)"; \ - MAJOR=$${VERSION%%.*}; \ - MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \ - if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \ - echo 1; \ - fi) +ifeq ($(OS),macos) + # Extract the major version + GUM_VERSION_MAJOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/\..*//') + # Extract the minor version (assumes format "MAJOR.MINOR[.PATCH...]") + GUM_VERSION_MINOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/^[^.]*\.//; s/\..*//') + + # Evaluate the version condition in a separate shell call + IS_GUM_16_6_PLUS := $(shell \ + if (( $(GUM_VERSION_MAJOR) > 16 || ( $(GUM_VERSION_MAJOR) == 16 && $(GUM_VERSION_MINOR) >= 6 ) )); then \ + echo 1; \ + fi) +else + IS_GUM_16_6_PLUS := $(shell VERSION="$(GUM_DEVKIT_VERSION)"; \ + MAJOR=$${VERSION%%.*}; \ + MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \ + if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \ + echo 1; \ + fi) +endif CFLAGS += $(if $(IS_GUM_16_6_PLUS),-DGUM_16_6_PLUS) From a85f0c0ef97135476292ee63e72a8fa365adea73 Mon Sep 17 00:00:00 2001 From: 5angjun Date: Sun, 30 Mar 2025 04:28:51 +0900 Subject: [PATCH 08/61] Add skip routine before writing det_plot_file --- src/afl-fuzz-stats.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 20da0434..8c13cd65 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -604,6 +604,8 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, void plot_profile_data(afl_state_t *afl, struct queue_entry *q) { + if (afl->skip_deterministic) { return; } + u64 current_ms = get_cur_time() - afl->start_time; u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); From 950b90abcd94adc9a81aff24e413529d94445d7f Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sun, 30 Mar 2025 16:04:01 +0000 Subject: [PATCH 09/61] avoid import already imported foreign corpus If no new foreign cases, mtime_max is 0 and this incorrectly reset last import mtime. --- src/afl-fuzz-init.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d8e7169d..f31511ff 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -668,7 +668,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) { } - afl->foreign_syncs[iter].mtime = mtime_max; + if (mtime_max > afl->foreign_syncs[iter].mtime) { + + afl->foreign_syncs[iter].mtime = mtime_max; + + } + free(nl); /* not tracked */ } From 992349e48ab8e261733898f1b4d2db7c3c56649f Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sun, 30 Mar 2025 16:02:56 +0000 Subject: [PATCH 10/61] fix memory leak in read_foreign_testcases --- src/afl-fuzz-init.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index d8e7169d..4add1b5a 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -567,6 +567,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) { } + free(nl); continue; } @@ -593,6 +594,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) { if (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) { if (first) PFATAL("Unable to access '%s'", fn2); + ck_free(fn2); continue; } @@ -634,19 +636,16 @@ void read_foreign_testcases(afl_state_t *afl, int first) { // as this could add duplicates of the startup input corpus int fd = open(fn2, O_RDONLY); - if (fd < 0) { + ck_free(fn2); - ck_free(fn2); - continue; - - } + if (fd < 0) { continue; } u8 fault; u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mem == MAP_FAILED) { - ck_free(fn2); + close(fd); continue; } From d1cab470bba213dcadef541c4b9c5966a33015c7 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Thu, 3 Apr 2025 01:02:53 +0000 Subject: [PATCH 11/61] fix memory leaks --- src/afl-fuzz-extras.c | 1 + src/afl-fuzz-skipdet.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index da996602..5ead8532 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -354,6 +354,7 @@ void load_extras(afl_state_t *afl, u8 *dir) { "Extra '%s' is too big (%s, limit is %s)", fn, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size), stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); + ck_free(fn); continue; } diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c index 8a927292..072b9b66 100644 --- a/src/afl-fuzz-skipdet.c +++ b/src/afl-fuzz-skipdet.c @@ -126,7 +126,12 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len); memset(inf_eff_map, 1, sizeof(u8) * len); - if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } + if (common_fuzz_stuff(afl, orig_buf, len)) { + + ck_free(inf_eff_map); + return 0; + + } u64 prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); u64 _prev_cksum = prev_cksum; @@ -154,7 +159,12 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, flip_range(out_buf, pos, flip_block_size); - if (common_fuzz_stuff(afl, out_buf, len)) return 0; + if (common_fuzz_stuff(afl, out_buf, len)) { + + ck_free(inf_eff_map); + return 0; + + } flip_range(out_buf, pos, flip_block_size); @@ -278,7 +288,13 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len); // clean exec cksum - if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + if (common_fuzz_stuff(afl, out_buf, len)) { + + ck_free(non_eff_bytes); + return 0; + + } + prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); } @@ -311,7 +327,13 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, before_skip_inf = afl->queued_items; - if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } + if (common_fuzz_stuff(afl, out_buf, len)) { + + ck_free(inf_eff_map); + ck_free(non_eff_bytes); + return 0; + + } out_buf[afl->stage_cur_byte] = orig; @@ -356,6 +378,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, cleanup_skipdet: + ck_free(inf_eff_map); if (fuzz_nearby) { u8 *nearby_bytes = (u8 *)ck_alloc(sizeof(u8) * len); From 0e35e56cc979acf3e2cb80d865a9fc6af3ef1d6a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Apr 2025 08:25:18 +0200 Subject: [PATCH 12/61] update changelog --- docs/Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 17d8c08a..361b57b5 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,8 @@ - Fixed a bug where after a fast restart of a full fuzzed corpus afl-fuzz terminates with "need at least one valid input seed that does not crash" - Small improvements to afl-*-config + - afl-fuzz: + - memory leak fixes by @kcwu - thanks! ### Version ++4.31c (release) From 5069551778e10d190c468622cfa3d047afa0a61b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Apr 2025 08:43:14 +0200 Subject: [PATCH 13/61] update changelog --- docs/Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 361b57b5..0fa0dc57 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,8 @@ - Small improvements to afl-*-config - afl-fuzz: - memory leak fixes by @kcwu - thanks! + - frida_mode: + - fixes for new MacOS + M4 hardware ### Version ++4.31c (release) From 5842ba87e55c4a2a5842deee7f59a783260bca11 Mon Sep 17 00:00:00 2001 From: Xeonacid Date: Thu, 3 Apr 2025 04:17:37 -0400 Subject: [PATCH 14/61] Define WORD_SIZE_64 for riscv64 --- include/config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/config.h b/include/config.h index 5ac0540d..94778e11 100644 --- a/include/config.h +++ b/include/config.h @@ -171,7 +171,8 @@ #define EXEC_TM_ROUND 20U /* 64bit arch MACRO */ -#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) +#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__) || \ + (defined(__riscv) && __riscv_xlen == 64)) #define WORD_SIZE_64 1 #endif From 58c5e2b96c5f446214d0fff72c560f93509248c7 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Thu, 3 Apr 2025 11:09:32 +0000 Subject: [PATCH 15/61] fix double free bug introduced by 73ab495b5d1a99722f4a2c2b1b9507daa7334fd9 --- src/afl-fuzz-skipdet.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c index 072b9b66..206a645b 100644 --- a/src/afl-fuzz-skipdet.c +++ b/src/afl-fuzz-skipdet.c @@ -126,12 +126,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len); memset(inf_eff_map, 1, sizeof(u8) * len); - if (common_fuzz_stuff(afl, orig_buf, len)) { - - ck_free(inf_eff_map); - return 0; - - } + if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; } u64 prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); u64 _prev_cksum = prev_cksum; @@ -159,12 +154,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, flip_range(out_buf, pos, flip_block_size); - if (common_fuzz_stuff(afl, out_buf, len)) { - - ck_free(inf_eff_map); - return 0; - - } + if (common_fuzz_stuff(afl, out_buf, len)) { return 0; } flip_range(out_buf, pos, flip_block_size); @@ -329,7 +319,6 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, if (common_fuzz_stuff(afl, out_buf, len)) { - ck_free(inf_eff_map); ck_free(non_eff_bytes); return 0; @@ -378,7 +367,6 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, cleanup_skipdet: - ck_free(inf_eff_map); if (fuzz_nearby) { u8 *nearby_bytes = (u8 *)ck_alloc(sizeof(u8) * len); From d21804bdd18408b63824aa99fee24be4be4b163a Mon Sep 17 00:00:00 2001 From: 20urc3 <94982366+20urc3@users.noreply.github.com> Date: Thu, 3 Apr 2025 15:30:45 +0100 Subject: [PATCH 16/61] Update afl-cmin Fix patch 1 --- afl-cmin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/afl-cmin b/afl-cmin index a88460a8..cbc328f2 100755 --- a/afl-cmin +++ b/afl-cmin @@ -432,7 +432,7 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" + cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d -a ! -path \"*/plots\" -a ! -path \"*/.state\" \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" From 68634964ef6f4e747d1850bf7989097ad7f74f30 Mon Sep 17 00:00:00 2001 From: 20urc3 <94982366+20urc3@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:28:31 +0100 Subject: [PATCH 17/61] Update afl-cmin --- afl-cmin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/afl-cmin b/afl-cmin index cbc328f2..6857d1b0 100755 --- a/afl-cmin +++ b/afl-cmin @@ -432,7 +432,7 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d -a ! -path \"*/plots\" -a ! -path \"*/.state\" \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" + cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d -a ! -path \"*/.state\" \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" From f17ea60a304bd745e62c353ed422fe4f5d6e22c4 Mon Sep 17 00:00:00 2001 From: 20urc3 <94982366+20urc3@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:49:43 +0100 Subject: [PATCH 18/61] Update afl-cmin removed `-a ! -path \"*/.state\"` --- afl-cmin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/afl-cmin b/afl-cmin index 6857d1b0..49e77b58 100755 --- a/afl-cmin +++ b/afl-cmin @@ -432,7 +432,7 @@ BEGIN { } else { stat_format = "-f '%z %N'" # *BSD, MacOS } - cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d -a ! -path \"*/.state\" \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" + cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'" #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" From ec07f531f895d8e6f41d7b4c63c4136352f8d5fc Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 5 Apr 2025 01:49:27 +0000 Subject: [PATCH 19/61] reduce skipdet_e memory usage By using bitmaps, the memory requirement for `q->skipdet_e->skip_eff_map` and `done_inf_map`, which previously scaled with the corpus size, is reduced to one-eighth of its original size. --- include/afl-fuzz.h | 12 ++++++++++++ src/afl-fuzz-bitmap.c | 12 ------------ src/afl-fuzz-one.c | 34 +++++++++++++++++----------------- src/afl-fuzz-skipdet.c | 18 +++++++++--------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index a96b4873..4a43e18d 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1452,6 +1452,18 @@ static inline int permissive_create(afl_state_t *afl, const char *fn) { } +static inline void bitmap_set(u8 *map, u32 index) { + + map[index / 8] |= (1u << (index % 8)); + +} + +static inline u8 bitmap_read(u8 *map, u32 index) { + + return (map[index / 8] >> (index % 8)) & 1; + +} + #if TESTCASE_CACHE == 1 #error define of TESTCASE_CACHE must be zero or larger than 1 #endif diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index bd3378f9..68115215 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -462,18 +462,6 @@ void write_crash_readme(afl_state_t *afl) { } -static inline void bitmap_set(u8 *map, u32 index) { - - map[index / 8] |= (1u << (index % 8)); - -} - -static inline u8 bitmap_read(u8 *map, u32 index) { - - return (map[index / 8] >> (index % 8)) & 1; - -} - /* Check if the result of an execve() during routine fuzzing is interesting, save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 36127964..1cc8f6e4 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -634,7 +634,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; - if (!skip_eff_map[afl->stage_cur_byte]) continue; + if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -754,7 +754,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; - if (!skip_eff_map[afl->stage_cur_byte]) continue; + if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -793,7 +793,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur >> 3; - if (!skip_eff_map[afl->stage_cur_byte]) continue; + if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -837,7 +837,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_cur_byte = afl->stage_cur; - if (!skip_eff_map[afl->stage_cur_byte]) continue; + if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -858,7 +858,7 @@ u8 fuzz_one_original(afl_state_t *afl) { for (i = 0; i < len; i++) { - if (skip_eff_map[i]) afl->blocks_eff_select += 1; + if (bitmap_read(skip_eff_map, i)) afl->blocks_eff_select += 1; } @@ -887,7 +887,7 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -930,7 +930,7 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -983,7 +983,7 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1067,7 +1067,7 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1197,7 +1197,7 @@ skip_bitflip: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1331,7 +1331,7 @@ skip_arith: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1391,7 +1391,7 @@ skip_arith: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1479,7 +1479,7 @@ skip_arith: /* Let's consult the effector map... */ - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1573,7 +1573,7 @@ skip_interest: u32 last_len = 0; - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1642,7 +1642,7 @@ skip_interest: for (i = 0; i <= (u32)len; ++i) { - if (!skip_eff_map[i % len]) continue; + if (!bitmap_read(skip_eff_map, i % len)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1708,7 +1708,7 @@ skip_user_extras: u32 last_len = 0; - if (!skip_eff_map[i]) continue; + if (!bitmap_read(skip_eff_map, i)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } @@ -1768,7 +1768,7 @@ skip_user_extras: for (i = 0; i <= (u32)len; ++i) { - if (!skip_eff_map[i % len]) continue; + if (!bitmap_read(skip_eff_map, i % len)) continue; if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; } diff --git a/src/afl-fuzz-skipdet.c b/src/afl-fuzz-skipdet.c index 206a645b..2197c101 100644 --- a/src/afl-fuzz-skipdet.c +++ b/src/afl-fuzz-skipdet.c @@ -237,26 +237,26 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, if (!skip_eff_map) { - skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len); + skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8); afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map; } else { - memset(skip_eff_map, 0, sizeof(u8) * len); + memset(skip_eff_map, 0, sizeof(u8) * (len + 7) / 8); } /* restore the starting point */ if (!done_inf_map) { - done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len); + done_inf_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8); afl->queue_cur->skipdet_e->done_inf_map = done_inf_map; } else { for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) { - if (done_inf_map[afl->stage_cur] == 0) break; + if (bitmap_read(done_inf_map, afl->stage_cur) == 0) break; } @@ -300,7 +300,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, afl->stage_cur_byte = afl->stage_cur; if (!inf_eff_map[afl->stage_cur_byte] || - skip_eff_map[afl->stage_cur_byte]) + bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue; if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; } @@ -339,7 +339,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, if (afl->queued_items != before_skip_inf) { - skip_eff_map[afl->stage_cur_byte] = 1; + bitmap_set(skip_eff_map, afl->stage_cur_byte); afl->queue_cur->skipdet_e->quick_eff_bytes += 1; if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; } @@ -349,7 +349,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf, } - done_inf_map[afl->stage_cur_byte] = 1; + bitmap_set(done_inf_map, afl->stage_cur_byte); } @@ -375,7 +375,7 @@ cleanup_skipdet: while (i < len) { // assume DWORD size, from i - 3 -> i + 3 - if (skip_eff_map[i]) { + if (bitmap_read(skip_eff_map, i)) { u32 fill_length = (i + 3 < len) ? 7 : len - i + 2; memset(nearby_bytes + i - 3, 1, fill_length); @@ -389,7 +389,7 @@ cleanup_skipdet: for (i = 0; i < len; i++) { - if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1; + if (nearby_bytes[i] && !non_eff_bytes[i]) bitmap_set(skip_eff_map, i); } From 969541b54ffc3324777b2a8eb615a6273ab0ec17 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 5 Apr 2025 03:02:56 +0000 Subject: [PATCH 20/61] fix potential q->trace_mini off by 1 overflow Be careful this change is incompatible with old version of fastresume.bin --- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 4d68c4c4..681b3e80 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -924,7 +924,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!q->trace_mini) { - u32 len = (afl->fsrv.map_size >> 3); + u32 len = ((afl->fsrv.map_size + 7) >> 3); q->trace_mini = (u8 *)ck_alloc(len); minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index fbd5b389..3f1703c4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2843,7 +2843,7 @@ int main(int argc, char **argv_orig, char **envp) { u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); u32 r = 8 + afl->fsrv.map_size * 4; u32 q_len = o_end - o_start; - u32 m_len = (afl->fsrv.map_size >> 3); + u32 m_len = ((afl->fsrv.map_size + 7) >> 3); struct queue_entry *q; for (u32 i = 0; i < afl->queued_items; i++) { @@ -3559,7 +3559,7 @@ stop_fuzzing: u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); u32 q_len = o_end - o_start; - u32 m_len = (afl->fsrv.map_size >> 3); + u32 m_len = ((afl->fsrv.map_size + 7) >> 3); struct queue_entry *q; afl->pending_not_fuzzed = afl->queued_items; From 2ecf28440ff1b381564e067baac917f42a0c7797 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 6 Apr 2025 12:16:34 +0800 Subject: [PATCH 21/61] Fix comments in for SAND --- include/asanfuzz.h | 10 +++++----- src/afl-fuzz.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/asanfuzz.h b/include/asanfuzz.h index 693a12b3..6dd28a7f 100644 --- a/include/asanfuzz.h +++ b/include/asanfuzz.h @@ -37,11 +37,11 @@ enum SanitizerAbstraction { - SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the - // most sensitive - UNIQUE_TRACE, - COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the - // least sensitive + SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate + // sensitive and default for SAND. + UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive. + COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the + // least sensitive }; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index fbd5b389..440ed8b0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2605,7 +2605,7 @@ int main(int argc, char **argv_orig, char **envp) { } else { - WARNF("Unknown abstraction: %s, fallback to unique trace.\n", + WARNF("Unknown abstraction: %s, fallback to simplified trace.\n", san_abstraction); afl->san_abstraction = SIMPLIFY_TRACE; From 58e4070573eb47b6a61c054ceae23532bf5426e4 Mon Sep 17 00:00:00 2001 From: mio Date: Sun, 6 Apr 2025 12:18:49 +0800 Subject: [PATCH 22/61] Update comments --- include/asanfuzz.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/asanfuzz.h b/include/asanfuzz.h index 6dd28a7f..17e8ac57 100644 --- a/include/asanfuzz.h +++ b/include/asanfuzz.h @@ -38,10 +38,11 @@ enum SanitizerAbstraction { SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate - // sensitive and default for SAND. - UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive. + // sensitive and default for SAND. Not missing bugs. + UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive + // and not missing bugs. COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the - // least sensitive + // least sensitive at a risk of missing ~20% bugs. }; From fc38904e259a109df9a6b3ef197b9b835e904951 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Apr 2025 10:08:29 +0200 Subject: [PATCH 23/61] fix --- src/afl-fuzz-queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 681b3e80..844eadb5 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -1330,7 +1330,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, // only realloc if necessary or useful // (a custom trim can make the testcase larger) - if (unlikely(len > old_len || len < old_len + 1024)) { + if (unlikely(len > old_len || len + 1024 < old_len)) { afl->q_testcase_cache_size += len - old_len; q->testcase_buf = (u8 *)realloc(q->testcase_buf, len); @@ -1364,7 +1364,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, if (likely(in != q->testcase_buf)) { // only realloc if we save memory - if (unlikely(len < old_len + 1024)) { + if (unlikely(len + 1024 < old_len)) { u8 *ptr = (u8 *)realloc(q->testcase_buf, len); From 7c349b6cdeddd6cdf250a31236eecb806186c788 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Apr 2025 10:13:13 +0200 Subject: [PATCH 24/61] increase fast resume version --- docs/Changelog.md | 1 + include/afl-fuzz.h | 2 ++ include/asanfuzz.h | 8 ++++---- src/afl-fuzz.c | 7 ++++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 0fa0dc57..3b8aaf84 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,7 @@ - Small improvements to afl-*-config - afl-fuzz: - memory leak fixes by @kcwu - thanks! + - some more nits and small memory saves thanks to @kcwu - frida_mode: - fixes for new MacOS + M4 hardware diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 4a43e18d..9404991b 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -353,6 +353,8 @@ enum { }; +#define FAST_RESUME_VERSION 0x01000000 + /* Python stuff */ #ifdef USE_PYTHON diff --git a/include/asanfuzz.h b/include/asanfuzz.h index 17e8ac57..c82ae3ae 100644 --- a/include/asanfuzz.h +++ b/include/asanfuzz.h @@ -39,10 +39,10 @@ enum SanitizerAbstraction { SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate // sensitive and default for SAND. Not missing bugs. - UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive - // and not missing bugs. - COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the - // least sensitive at a risk of missing ~20% bugs. + UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive + // and not missing bugs. + COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the + // least sensitive at a risk of missing ~20% bugs. }; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2e8acaa7..f6921e8c 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2326,8 +2326,8 @@ int main(int argc, char **argv_orig, char **envp) { u8 ver_string[8]; u64 *ver = (u64 *)ver_string; - u64 expect_ver = - afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + u64 expect_ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode + + (sizeof(struct queue_entry) << 1); if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string)) @@ -3546,7 +3546,8 @@ stop_fuzzing: u8 ver_string[8]; u32 w = 0; u64 *ver = (u64 *)ver_string; - *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + *ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode + + (sizeof(struct queue_entry) << 1); ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string"); ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); From c5e511302f56df044df4888341c21ffbde259028 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Tue, 8 Apr 2025 09:37:20 +0800 Subject: [PATCH 25/61] Update FAQ.md the default schedule was changed to EXPLORE since 4.10a --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index ca857a5b..cc88cdc6 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -236,7 +236,7 @@ If you find an interesting or important question missing, submit it via [AFLFast](https://github.com/mboehme/aflfast), however, modified to be more effective and several more modes added. - The most effective modes are `-p fast` (default) and `-p explore`. + The most effective modes are `-p explore` (default) and `-p fast`. If you fuzz with several parallel afl-fuzz instances, then it is beneficial to assign a different schedule to each instance, however the majority should From 55c9c4ff19fb2429381c611ef84e933f3644ce37 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 8 Apr 2025 11:32:00 +0200 Subject: [PATCH 26/61] deprecate some queue/.state files --- docs/Changelog.md | 1 + include/afl-fuzz.h | 2 -- src/afl-fuzz-extras.c | 6 ++---- src/afl-fuzz-init.c | 14 -------------- src/afl-fuzz-queue.c | 39 --------------------------------------- src/afl-fuzz-run.c | 7 +------ src/afl-fuzz.c | 11 +---------- 7 files changed, 5 insertions(+), 75 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 3b8aaf84..0c616d4f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,7 @@ - afl-fuzz: - memory leak fixes by @kcwu - thanks! - some more nits and small memory saves thanks to @kcwu + - remove deprecated files from queue/.state - frida_mode: - fixes for new MacOS + M4 hardware diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 9404991b..f21f2dda 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1184,8 +1184,6 @@ void deinit_py(void *); /* Queue */ void mark_as_det_done(afl_state_t *, struct queue_entry *); -void mark_as_variable(afl_state_t *, struct queue_entry *); -void mark_as_redundant(afl_state_t *, struct queue_entry *, u8); void add_to_queue(afl_state_t *, u8 *, u32, u8); void destroy_queue(afl_state_t *); void update_bitmap_score(afl_state_t *, struct queue_entry *); diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 5ead8532..09338bb6 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -743,10 +743,8 @@ void save_auto(afl_state_t *afl) { for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { - u8 *fn = alloc_printf( - "%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i, - afl->file_extension ? "." : "", - afl->file_extension ? (const char *)afl->file_extension : ""); + u8 *fn = + alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i); s32 fd; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 3472e675..e35ed2a3 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -753,8 +753,6 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - // if (getenv("MYTEST")) afl->in_place_resume = 1; - if (nl_cnt) { u32 done = 0; @@ -2316,18 +2314,6 @@ void setup_dirs_fds(afl_state_t *afl) { if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); - /* The set of paths currently deemed redundant. */ - - tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir); - if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } - ck_free(tmp); - - /* The set of paths showing variable behavior. */ - - tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir); - if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } - ck_free(tmp); - /* Sync directory for keeping track of cooperating fuzzers. */ if (afl->sync_id) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 844eadb5..3adbc83d 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -440,30 +440,6 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { } -/* Mark as variable. Create symlinks if possible to make it easier to examine - the files. */ - -void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { - - char fn[PATH_MAX]; - char ldest[PATH_MAX]; - - char *fn_name = strrchr((char *)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)) { - - s32 fd = permissive_create(afl, fn); - if (fd >= 0) { close(fd); } - - } - - q->var_behavior = 1; - -} - /* Mark / unmark as redundant (edge-only). This is not used for restoring state, but may be useful for post-processing datasets. */ @@ -471,8 +447,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { if (likely(state == q->fs_redundant)) { return; } - char fn[PATH_MAX]; - q->fs_redundant = state; if (likely(q->fs_redundant)) { @@ -486,22 +460,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } - sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, - strrchr((char *)q->fname, '/') + 1); - if (state) { - s32 fd; - if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } - fd = permissive_create(afl, fn); - if (fd >= 0) { close(fd); } - - } else { - - if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ - - } } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index c40af235..dc39db06 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -682,12 +682,7 @@ abort_calibration: afl->var_byte_count = count_bytes(afl, afl->var_bytes); - if (!q->var_behavior) { - - mark_as_variable(afl, q); - ++afl->queued_variable; - - } + if (!q->var_behavior) { ++afl->queued_variable; } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f6921e8c..7d796467 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1759,16 +1759,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } - if (afl->afl_env.afl_autoresume) { - - afl->autoresume = 1; - if (afl->in_place_resume) { - - SAYF("AFL_AUTORESUME has no effect for '-i -'"); - - } - - } + if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; } if (afl->afl_env.afl_hang_tmout) { From 57466909e43f1891b90a3cdc315eea3c8c9b0501 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 8 Apr 2025 11:33:05 +0200 Subject: [PATCH 27/61] remove outdated doc --- docs/afl-fuzz_approach.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/afl-fuzz_approach.md b/docs/afl-fuzz_approach.md index 4ebce154..58553fbd 100644 --- a/docs/afl-fuzz_approach.md +++ b/docs/afl-fuzz_approach.md @@ -385,10 +385,6 @@ there are several things to look at: subsequent iterations (e.g., due to incomplete clean-up or reinitialization of the state) and that most of the fuzzing effort goes to waste. -The paths where variable behavior is detected are marked with a matching entry -in the `/queue/.state/variable_behavior/` directory, so you can look -them up easily. - ### CPU load ``` From 5df3cdbc0bcbc7b29c79d07884a6a05d7820cac6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 8 Apr 2025 17:43:26 +0200 Subject: [PATCH 28/61] effeciency fix for SAND --- src/afl-fuzz-bitmap.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 68115215..21355845 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -527,8 +527,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits, afl->fsrv.map_size); - classify_counts_mem((_AFL_INTSIZEVAR *)afl->san_fsrvs[0].trace_bits, - afl->fsrv.map_size); simplify_trace(afl, afl->san_fsrvs[0].trace_bits); // Note: Original SAND implementation used XXHASH32 From 891b7f48f04405ebe7f7936f79fe389958c6f3da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 9 Apr 2025 10:48:34 +0200 Subject: [PATCH 29/61] nits --- include/config.h | 4 ++-- src/afl-fuzz-bitmap.c | 14 -------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/include/config.h b/include/config.h index 94778e11..b4c0cb54 100644 --- a/include/config.h +++ b/include/config.h @@ -201,8 +201,8 @@ /* Maximum number of unique hangs or crashes to record: */ -#define KEEP_UNIQUE_HANG 500U -#define KEEP_UNIQUE_CRASH 10000U +#define KEEP_UNIQUE_HANG 512U +#define KEEP_UNIQUE_CRASH 25600U /* Baseline number of random tweaks during a single 'havoc' stage: */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 21355845..dce672a3 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -785,13 +785,6 @@ may_save_fault: if (likely(!afl->non_instrumented_mode)) { - if (unlikely(!classified)) { - - classify_counts(&afl->fsrv); - classified = 1; - - } - simplify_trace(afl, afl->fsrv.trace_bits); if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; } @@ -925,13 +918,6 @@ may_save_fault: if (likely(!afl->non_instrumented_mode)) { - if (unlikely(!classified)) { - - classify_counts(&afl->fsrv); - classified = 1; - - } - simplify_trace(afl, afl->fsrv.trace_bits); if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; } From 4ff2673895c85ac6ac15dffc999e05a43d8d1521 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 9 Apr 2025 14:21:42 +0200 Subject: [PATCH 30/61] fix update_bitmap_score when no current trace is present --- docs/Changelog.md | 1 + include/afl-fuzz.h | 2 +- src/afl-fuzz-bitmap.c | 6 +-- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-queue.c | 104 +++++++++++++++++++++------------------- src/afl-fuzz-run.c | 4 +- src/afl-fuzz.c | 4 +- src/afl-showmap.c | 3 +- 8 files changed, 65 insertions(+), 61 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 0c616d4f..f34d5437 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,7 @@ - memory leak fixes by @kcwu - thanks! - some more nits and small memory saves thanks to @kcwu - remove deprecated files from queue/.state + - fix bitmap update function if no current trace is present - frida_mode: - fixes for new MacOS + M4 hardware diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f21f2dda..f475498a 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1186,7 +1186,7 @@ void deinit_py(void *); void mark_as_det_done(afl_state_t *, struct queue_entry *); void add_to_queue(afl_state_t *, u8 *, u32, u8); void destroy_queue(afl_state_t *); -void update_bitmap_score(afl_state_t *, struct queue_entry *); +void update_bitmap_score(afl_state_t *, struct queue_entry *, bool); void cull_queue(afl_state_t *); u32 calculate_score(afl_state_t *, struct queue_entry *); diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index dce672a3..0d3a1609 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -490,8 +490,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u8 fn[PATH_MAX]; u8 *queue_fn = ""; - u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0, - need_hash = 1; + u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1; s32 fd; u64 cksum = 0; u32 cksum_simplified = 0, cksum_unique = 0; @@ -508,7 +507,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); - classified = 1; need_hash = 0; cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -632,7 +630,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, afl->san_case_status |= NON_COV_INCREASE_BUG; fault = san_fault; - classified = new_bits; goto may_save_fault; } @@ -640,7 +637,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, } fault = san_fault; - classified = new_bits; save_to_queue: diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index dbc23ac6..7c7a4b9f 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -636,7 +636,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, q->len = out_len; memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size); - update_bitmap_score(afl, q); + update_bitmap_score(afl, q, true); } diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 3adbc83d..ea6d902a 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -794,7 +794,8 @@ void destroy_queue(afl_state_t *afl) { previous contender, or if the contender has a more favorable speed x size factor. */ -void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { +void update_bitmap_score(afl_state_t *afl, struct queue_entry *q, + bool have_trace) { u32 i; u64 fav_factor; @@ -824,75 +825,80 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } - /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous - winner, and how it compares to us. */ - for (i = 0; i < afl->fsrv.map_size; ++i) { + if (have_trace) { - if (afl->fsrv.trace_bits[i]) { + /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous + winner, and how it compares to us. */ + for (i = 0; i < afl->fsrv.map_size; ++i) { - if (afl->top_rated[i]) { + if (afl->fsrv.trace_bits[i]) { - /* Faster-executing or smaller test cases are favored. */ - u64 top_rated_fav_factor; - u64 top_rated_fuzz_p2; + if (afl->top_rated[i]) { - if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { + /* Faster-executing or smaller test cases are favored. */ + u64 top_rated_fav_factor; + u64 top_rated_fuzz_p2; - top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { - } else if (unlikely(afl->schedule == RARE)) { + top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison - top_rated_fuzz_p2 = - next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); + } else if (unlikely(afl->schedule == RARE)) { - } else { + top_rated_fuzz_p2 = + next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); - top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level; + } else { + + top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level; + + } + + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { + + top_rated_fav_factor = afl->top_rated[i]->len << 2; + + } else { + + top_rated_fav_factor = + afl->top_rated[i]->exec_us * afl->top_rated[i]->len; + + } + + if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; } + + if (likely(fav_factor > top_rated_fav_factor)) { continue; } + + /* Looks like we're going to win. Decrease ref count for the + previous winner, discard its afl->fsrv.trace_bits[] if necessary. + */ + + if (!--afl->top_rated[i]->tc_ref) { + + ck_free(afl->top_rated[i]->trace_mini); + afl->top_rated[i]->trace_mini = NULL; + + } } - if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { + /* Insert ourselves as the new winner. */ - top_rated_fav_factor = afl->top_rated[i]->len << 2; + afl->top_rated[i] = q; + ++q->tc_ref; - } else { + if (!q->trace_mini) { - top_rated_fav_factor = - afl->top_rated[i]->exec_us * afl->top_rated[i]->len; + u32 len = ((afl->fsrv.map_size + 7) >> 3); + q->trace_mini = (u8 *)ck_alloc(len); + minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); } - if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; } - - if (likely(fav_factor > top_rated_fav_factor)) { continue; } - - /* Looks like we're going to win. Decrease ref count for the - previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ - - if (!--afl->top_rated[i]->tc_ref) { - - ck_free(afl->top_rated[i]->trace_mini); - afl->top_rated[i]->trace_mini = NULL; - - } + afl->score_changed = 1; } - /* Insert ourselves as the new winner. */ - - afl->top_rated[i] = q; - ++q->tc_ref; - - if (!q->trace_mini) { - - u32 len = ((afl->fsrv.map_size + 7) >> 3); - q->trace_mini = (u8 *)ck_alloc(len); - minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); - - } - - afl->score_changed = 1; - } } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index dc39db06..7dfa7a30 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -652,7 +652,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, afl->total_bitmap_size += q->bitmap_size; ++afl->total_bitmap_entries; - update_bitmap_score(afl, q); + update_bitmap_score(afl, q, true); /* If this case didn't result in new output from the instrumentation, tell parent. This is a non-critical problem, but something to warn the user @@ -1161,7 +1161,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len); memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size); - update_bitmap_score(afl, q); + update_bitmap_score(afl, q, true); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7d796467..584b664e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2857,7 +2857,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->total_bitmap_size += q->bitmap_size; ++afl->total_bitmap_entries; - update_bitmap_score(afl, q); + update_bitmap_score(afl, q, false); if (q->was_fuzzed) { --afl->pending_not_fuzzed; } @@ -3231,7 +3231,7 @@ int main(int argc, char **argv_orig, char **envp) { if (likely(!afl->queue_buf[i]->disabled)) { - update_bitmap_score(afl, afl->queue_buf[i]); + update_bitmap_score(afl, afl->queue_buf[i], false); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 6cd89779..77765fba 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -159,10 +159,11 @@ void show_stats(afl_state_t *afl) { } -void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { +void update_bitmap_score(afl_state_t *afl, struct queue_entry *q, bool x) { (void)afl; (void)q; + (void)x; } From 920c7fe71a8d11a7871a28d3ed0905c555260d11 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 20:18:14 +0800 Subject: [PATCH 31/61] Fix sand due to default schedule change --- include/coverage-32.h | 15 +-------------- include/coverage-64.h | 15 +-------------- src/afl-fuzz-bitmap.c | 20 +++++++++++++++++--- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/include/coverage-32.h b/include/coverage-32.h index f5b0056f..9932f240 100644 --- a/include/coverage-32.h +++ b/include/coverage-32.h @@ -69,20 +69,7 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { - - u32 *mem = (u32 *)fsrv->trace_bits; - u32 i = (fsrv->map_size >> 2); - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { *mem = classify_word(*mem); } - - mem++; - - } - + classify_counts_mem((u32 *)fsrv->trace_bits, fsrv->map_size); } /* Updates the virgin bits, then reflects whether a new count or a new tuple is diff --git a/include/coverage-64.h b/include/coverage-64.h index 22aa37f4..376658d5 100644 --- a/include/coverage-64.h +++ b/include/coverage-64.h @@ -63,20 +63,7 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { - - u64 *mem = (u64 *)fsrv->trace_bits; - u32 i = (fsrv->map_size >> 3); - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { *mem = classify_word(*mem); } - - mem++; - - } - + classify_counts_mem((u64 *)fsrv->trace_bits, afl->map_size); } inline void classify_counts_mem(u64 *mem, u32 size) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0d3a1609..0ab5e307 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -552,7 +552,17 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->san_binary_length) && likely(afl->san_abstraction == UNIQUE_TRACE)) { - + + // If schedule is not FAST..EXPLORE, we need to classify here + // Note: SAND was evaluated under FAST schedule but should also work + // with other scedules. + if (!classified) { + classify_counts_mem( + (u64*)afl->fsrv.trace_bits, + afl->fsrv.map_size + ); + classified = 1; + } cksum_unique = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) && @@ -615,8 +625,12 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, /* If we are in coverage increasing abstraction and have fed input to sanitizers, we are sure it has new bits.*/ - new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); - + if (classified) { + /* We could have classified the bits in SAND with UNIQUE_TRACE */ + new_bits = has_new_bits(afl, afl->virgin_bits); + } else { + new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); + } } if (likely(!new_bits)) { From 6223ddf6d2f9a6c299c0a1a543a44e7df63b0ff8 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 20:21:18 +0800 Subject: [PATCH 32/61] Changes not saved =( --- include/coverage-64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/coverage-64.h b/include/coverage-64.h index 376658d5..34d64303 100644 --- a/include/coverage-64.h +++ b/include/coverage-64.h @@ -63,7 +63,7 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { - classify_counts_mem((u64 *)fsrv->trace_bits, afl->map_size); + classify_counts_mem((u64 *)fsrv->trace_bits, fsrv->map_size); } inline void classify_counts_mem(u64 *mem, u32 size) { From eb0b8b2c5ca20b5e2c07e98ce72efd77cbc5179d Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 21:13:23 +0800 Subject: [PATCH 33/61] No longer need classify_counts_mem --- src/afl-fuzz-bitmap.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0ab5e307..8d359f30 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -557,10 +557,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, // Note: SAND was evaluated under FAST schedule but should also work // with other scedules. if (!classified) { - classify_counts_mem( - (u64*)afl->fsrv.trace_bits, - afl->fsrv.map_size - ); + classify_counts(&afl->fsrv); classified = 1; } cksum_unique = From 6b71ca78097b4cdc7aecc3bf15063c11a15786b6 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 21:14:47 +0800 Subject: [PATCH 34/61] Also remove declaration --- include/coverage-32.h | 30 ++++++++++++------------------ include/coverage-64.h | 10 ++-------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/include/coverage-32.h b/include/coverage-32.h index 9932f240..0951531b 100644 --- a/include/coverage-32.h +++ b/include/coverage-32.h @@ -9,7 +9,6 @@ u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end); u32 classify_word(u32 word); -void classify_counts_mem(u32 *mem, u32 size); inline u32 classify_word(u32 word) { @@ -24,22 +23,6 @@ inline u32 classify_word(u32 word) { } -inline void classify_counts_mem(u32 *mem, u32 size) { - - u32 i = (size >> 2); - - while (i--) { - - /* Optimize for sparse bitmaps. */ - - if (unlikely(*mem)) { *mem = classify_word(*mem); } - - mem++; - - } - -} - void simplify_trace(afl_state_t *afl, u8 *bytes) { u32 *mem = (u32 *)bytes; @@ -69,7 +52,18 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { - classify_counts_mem((u32 *)fsrv->trace_bits, fsrv->map_size); + u32 *mem = (u32 *)fsrv->trace_bits; + u32 i = (fsrv->map_size >> 2); + + while (i--) { + + /* Optimize for sparse bitmaps. */ + + if (unlikely(*mem)) { *mem = classify_word(*mem); } + + mem++; + + } } /* Updates the virgin bits, then reflects whether a new count or a new tuple is diff --git a/include/coverage-64.h b/include/coverage-64.h index 34d64303..8594c29d 100644 --- a/include/coverage-64.h +++ b/include/coverage-64.h @@ -13,7 +13,6 @@ u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end); u64 classify_word(u64 word); -void classify_counts_mem(u64 *mem, u32 size); inline u64 classify_word(u64 word) { @@ -63,12 +62,8 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { - classify_counts_mem((u64 *)fsrv->trace_bits, fsrv->map_size); -} - -inline void classify_counts_mem(u64 *mem, u32 size) { - - u32 i = (size >> 3); + u64 *mem = (u64 *)fsrv->trace_bits; + u32 i = (fsrv->map_size >> 3); while (i--) { @@ -79,7 +74,6 @@ inline void classify_counts_mem(u64 *mem, u32 size) { mem++; } - } /* Updates the virgin bits, then reflects whether a new count or a new tuple is From bc11bd7661bf247f5e5fc38bde4fcbbfe1015c4e Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 21:26:07 +0800 Subject: [PATCH 35/61] Fix comments --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 8d359f30..8b543537 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -553,7 +553,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->san_binary_length) && likely(afl->san_abstraction == UNIQUE_TRACE)) { - // If schedule is not FAST..EXPLORE, we need to classify here + // If schedule is not FAST..RARE, we need to classify counts here // Note: SAND was evaluated under FAST schedule but should also work // with other scedules. if (!classified) { From 112d90656b8bd79b57e799c4b3059d776a78423f Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 9 Apr 2025 21:34:33 +0800 Subject: [PATCH 36/61] rebase against dev --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 8b543537..17e1ea57 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -490,7 +490,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u8 fn[PATH_MAX]; u8 *queue_fn = ""; - u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1; + u8 new_bits = 0, keeping = 0, res, is_timeout = 0, classified = 0, need_hash = 1; s32 fd; u64 cksum = 0; u32 cksum_simplified = 0, cksum_unique = 0; From 161905c2fc5372cfd91dc22c5e4441c969c0deff Mon Sep 17 00:00:00 2001 From: 5angjun Date: Wed, 9 Apr 2025 23:37:16 +0900 Subject: [PATCH 37/61] fix: correct rescoring logic with minimal executions Previous scoring logic did not correctly rescore all queue entries. This patch ensures rescoring works under the updated scheduling logic, while minimizing executions per feedback from PR #2363. Based on feedback from: https://github.com/AFLplusplus/AFLplusplus/pull/2363 --- include/afl-fuzz.h | 6 ++ src/afl-fuzz-queue.c | 172 +++++++++++++++++++++++++++++++++++++++++++ src/afl-fuzz-state.c | 4 +- src/afl-fuzz.c | 10 +-- 4 files changed, 182 insertions(+), 10 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f475498a..806aecf9 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -721,6 +721,8 @@ typedef struct afl_state { struct queue_entry **top_rated; /* Top entries for bitmap bytes */ + u32 **top_rated_candidates; /* Candidate IDs per bitmap index */ + struct extra_data *extras; /* Extra tokens to fuzz with */ u32 extras_cnt; /* Total number of tokens read */ @@ -862,6 +864,8 @@ typedef struct afl_state { struct skipdet_global *skipdet_g; + s64 last_scored_idx; /* Index of the last queue entry re-scored */ + #ifdef INTROSPECTION char mutation[8072]; char m_tmp[4096]; @@ -1189,6 +1193,8 @@ void destroy_queue(afl_state_t *); void update_bitmap_score(afl_state_t *, struct queue_entry *, bool); void cull_queue(afl_state_t *); u32 calculate_score(afl_state_t *, struct queue_entry *); +void recalculate_all_scores(afl_state_t *); +void update_bitmap_rescore(afl_state_t *, struct queue_entry *, u32); /* Bitmap */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index ea6d902a..74d35fe5 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -992,6 +992,178 @@ void cull_queue(afl_state_t *afl) { } +/* Re-selects top_rated[] entries based on the current fuzzing schedule. + Each queued entry is executed once to collect trace_bits, and potential + candidates for each bitmap index are stored. + + The candidate list format is [count][id1][id2]... as a u32 array, + where 'count' indicates how many queue IDs hit that index. */ + +void recalculate_all_scores(afl_state_t *afl) { + + u8 *in_buf; + u32 i; + u32 j; + + for (i = afl->last_scored_idx + 1; i < afl->queued_items; i++) { + + if (likely(!afl->queue_buf[i]->disabled)) { + + in_buf = queue_testcase_get(afl, afl->queue_buf[i]); + (void)write_to_testcase(afl, in_buf, afl->queue_buf[i]->len, 1); + (void)fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + + for (j = 0; j < afl->fsrv.map_size; ++j) { + + if (afl->fsrv.trace_bits[j]) { + + u32 *candidate_ids = afl->top_rated_candidates[j]; + u32 id = afl->queue_buf[i]->id; + + if (!candidate_ids) { + // first candidate: [count][id] + candidate_ids = ck_alloc(sizeof(u32) * 2); + candidate_ids[0] = 1; // count = 1 + candidate_ids[1] = id; // first ID + } else { + u32 count = candidate_ids[0]; + + candidate_ids = ck_realloc(candidate_ids, sizeof(u32) * (count + 2)); + candidate_ids[0] = count + 1; // increment the count + candidate_ids[count + 1] = id; // append the new ID to the end + + //fprintf(stderr, "enroll candidate[%u][%u] %u\n", i, j, id); + } + + afl->top_rated_candidates[j] = candidate_ids; + + } + } + + + } + + afl->last_scored_idx = i; + + } + + for (i = 0; i < afl->fsrv.map_size; ++i) { + + u32 *candidate_ids = afl->top_rated_candidates[i]; + if(candidate_ids) { + u32 count = candidate_ids[0]; + + for(u32 k = 0; k < count; k++) { + u32 id = candidate_ids[k + 1]; + struct queue_entry *entry = afl->queue_buf[id]; + update_bitmap_rescore(afl, entry, i); + } + + } + + } + +} + +/* Re-evaluates top-rated entries without checking trace_bits. + Unlike update_bitmap_score(), this function assumes the trace + information is already known and only compares entries */ + +void update_bitmap_rescore(afl_state_t *afl, struct queue_entry *q, u32 index) { + + u32 i = index; + u64 fav_factor; + u64 fuzz_p2; + + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { + + fuzz_p2 = 0; // Skip the fuzz_p2 comparison + + } else if (unlikely(afl->schedule == RARE)) { + + fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]); + + } else { + + fuzz_p2 = q->fuzz_level; + + } + + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { + + fav_factor = q->len << 2; + + } else { + + fav_factor = q->exec_us * q->len; + + } + + if (afl->top_rated[i]) { + + /* Faster-executing or smaller test cases are favored. */ + u64 top_rated_fav_factor; + u64 top_rated_fuzz_p2; + + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { + + top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison + + } else if (unlikely(afl->schedule == RARE)) { + + top_rated_fuzz_p2 = + next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]); + + } else { + + top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level; + + } + + if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) { + + top_rated_fav_factor = afl->top_rated[i]->len << 2; + + } else { + + top_rated_fav_factor = + afl->top_rated[i]->exec_us * afl->top_rated[i]->len; + + } + + if (likely(fuzz_p2 > top_rated_fuzz_p2)) { return; } + + if (likely(fav_factor > top_rated_fav_factor)) { return; } + + /* Looks like we're going to win. Decrease ref count for the + previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ + + if (!--afl->top_rated[i]->tc_ref) { + + ck_free(afl->top_rated[i]->trace_mini); + afl->top_rated[i]->trace_mini = NULL; + + } + + } + + /* Insert ourselves as the new winner. */ + + afl->top_rated[i] = q; + ++q->tc_ref; + + if (!q->trace_mini) { + + u32 len = (afl->fsrv.map_size >> 3); + q->trace_mini = (u8 *)ck_alloc(len); + minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); + + } + + afl->score_changed = 1; + +} + /* Calculate case desirability score to adjust the length of havoc fuzzing. A helper function for fuzz_one(). Maybe some of these constants should go into config.h. */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 11554369..b346d86d 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -106,7 +106,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000; afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL; afl->q_testcase_max_cache_entries = 64 * 1024; - + afl->last_scored_idx = -1; + #ifdef HAVE_AFFINITY afl->cpu_aff = -1; /* Selected CPU core */ #endif /* HAVE_AFFINITY */ @@ -116,6 +117,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->virgin_crash = ck_alloc(map_size); afl->var_bytes = ck_alloc(map_size); afl->top_rated = ck_alloc(map_size * sizeof(void *)); + afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32)); afl->clean_trace = ck_alloc(map_size); afl->clean_trace_custom = ck_alloc(map_size); afl->first_trace = ck_alloc(map_size); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 584b664e..0f044c66 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -3227,15 +3227,7 @@ int main(int argc, char **argv_orig, char **envp) { } // we must recalculate the scores of all queue entries - for (u32 i = 0; i < afl->queued_items; i++) { - - if (likely(!afl->queue_buf[i]->disabled)) { - - update_bitmap_score(afl, afl->queue_buf[i], false); - - } - - } + recalculate_all_scores(afl); } From 939171952dd6ac5cd3501bff942a717efdba626e Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 10 Apr 2025 12:35:00 +0800 Subject: [PATCH 38/61] Fix missing classified accidentally removed by 4ff2673 --- src/afl-fuzz-bitmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 17e1ea57..1b43b381 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -468,6 +468,7 @@ void write_crash_readme(afl_state_t *afl) { u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { + u8 classified = 0; if (unlikely(len == 0)) { return 0; } @@ -477,6 +478,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, classify_counts(&afl->fsrv); u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + classified = 1; // Saturated increment if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) @@ -490,7 +492,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u8 fn[PATH_MAX]; u8 *queue_fn = ""; - u8 new_bits = 0, keeping = 0, res, is_timeout = 0, classified = 0, need_hash = 1; + u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1; s32 fd; u64 cksum = 0; u32 cksum_simplified = 0, cksum_unique = 0; From 6cbe58ff55e160ce304562ba345b3c474954f29b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 10 Apr 2025 09:30:18 +0200 Subject: [PATCH 39/61] code format --- include/coverage-32.h | 8 +++++--- include/coverage-64.h | 8 +++++--- src/afl-fuzz-bitmap.c | 11 ++++++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/coverage-32.h b/include/coverage-32.h index 0951531b..e26affb0 100644 --- a/include/coverage-32.h +++ b/include/coverage-32.h @@ -7,8 +7,8 @@ #define _AFL_INTSIZEVAR u32 -u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end); -u32 classify_word(u32 word); +u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end); +u32 classify_word(u32 word); inline u32 classify_word(u32 word) { @@ -52,8 +52,9 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { + u32 *mem = (u32 *)fsrv->trace_bits; - u32 i = (fsrv->map_size >> 2); + u32 i = (fsrv->map_size >> 2); while (i--) { @@ -64,6 +65,7 @@ inline void classify_counts(afl_forkserver_t *fsrv) { mem++; } + } /* Updates the virgin bits, then reflects whether a new count or a new tuple is diff --git a/include/coverage-64.h b/include/coverage-64.h index 8594c29d..7b854958 100644 --- a/include/coverage-64.h +++ b/include/coverage-64.h @@ -11,8 +11,8 @@ #include #endif -u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end); -u64 classify_word(u64 word); +u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end); +u64 classify_word(u64 word); inline u64 classify_word(u64 word) { @@ -62,8 +62,9 @@ void simplify_trace(afl_state_t *afl, u8 *bytes) { } inline void classify_counts(afl_forkserver_t *fsrv) { + u64 *mem = (u64 *)fsrv->trace_bits; - u32 i = (fsrv->map_size >> 3); + u32 i = (fsrv->map_size >> 3); while (i--) { @@ -74,6 +75,7 @@ inline void classify_counts(afl_forkserver_t *fsrv) { mem++; } + } /* Updates the virgin bits, then reflects whether a new count or a new tuple is diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 1b43b381..6a754a40 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -468,6 +468,7 @@ void write_crash_readme(afl_state_t *afl) { u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { + u8 classified = 0; if (unlikely(len == 0)) { return 0; } @@ -554,14 +555,17 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, if (unlikely(afl->san_binary_length) && likely(afl->san_abstraction == UNIQUE_TRACE)) { - + // If schedule is not FAST..RARE, we need to classify counts here // Note: SAND was evaluated under FAST schedule but should also work // with other scedules. if (!classified) { + classify_counts(&afl->fsrv); classified = 1; + } + cksum_unique = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) && @@ -625,11 +629,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, /* If we are in coverage increasing abstraction and have fed input to sanitizers, we are sure it has new bits.*/ if (classified) { + /* We could have classified the bits in SAND with UNIQUE_TRACE */ new_bits = has_new_bits(afl, afl->virgin_bits); + } else { + new_bits = has_new_bits_unclassified(afl, afl->virgin_bits); + } + } if (likely(!new_bits)) { From bd631c73a2caf20058871e5415377a5b058787ae Mon Sep 17 00:00:00 2001 From: 5angjun Date: Thu, 10 Apr 2025 18:41:32 +0900 Subject: [PATCH 40/61] Enable conditional allocation for cycle schedules --- src/afl-fuzz-state.c | 1 - src/afl-fuzz.c | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b346d86d..9a8b45a3 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -117,7 +117,6 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->virgin_crash = ck_alloc(map_size); afl->var_bytes = ck_alloc(map_size); afl->top_rated = ck_alloc(map_size * sizeof(void *)); - afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32)); afl->clean_trace = ck_alloc(map_size); afl->clean_trace_custom = ck_alloc(map_size); afl->first_trace = ck_alloc(map_size); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0f044c66..1170c303 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1750,6 +1750,12 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->cycle_schedules) { + + afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32)); + + } + afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); From b64dd0a1ec5bd593b489c231594ed9988c586748 Mon Sep 17 00:00:00 2001 From: 5angjun Date: Thu, 10 Apr 2025 22:50:42 +0900 Subject: [PATCH 41/61] add cleanup for top_rated_candidates in afl_state_deinit() --- src/afl-fuzz-state.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 9a8b45a3..83d92080 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -739,6 +739,19 @@ void afl_state_deinit(afl_state_t *afl) { if (afl->pass_stats) { ck_free(afl->pass_stats); } if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); } if (afl->cmplog_binary) { ck_free(afl->cmplog_binary); } + if (afl->cycle_schedules) { + + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + + if (afl->top_rated_candidates[i]) { + ck_free(afl->top_rated_candidates[i]); + } + + } + + ck_free(afl->top_rated_candidates); + + } afl_free(afl->queue_buf); afl_free(afl->out_buf); From 3c8016e0716c732ea20d925e9ddec43f691da7cc Mon Sep 17 00:00:00 2001 From: w1redch4d Date: Thu, 10 Apr 2025 19:21:14 +0530 Subject: [PATCH 42/61] fixed qbdi mode to work out of the box --- include/android-ashmem.h | 2 +- utils/qbdi_mode/template.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 065c213b..174c655f 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -30,7 +30,7 @@ int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { int ret = 0; if (__cmd == IPC_RMID) { - int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); + unsigned int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); struct ashmem_pin pin = {0, length}; ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); close(__shmid); diff --git a/utils/qbdi_mode/template.cpp b/utils/qbdi_mode/template.cpp index 3630ae3f..2f66b3df 100755 --- a/utils/qbdi_mode/template.cpp +++ b/utils/qbdi_mode/template.cpp @@ -11,12 +11,12 @@ #include #ifdef __ANDROID__ - #include "../include/android-ashmem.h" + #include "../../include/android-ashmem.h" #endif #include #include -#include "../config.h" +#include "../../config.h" #include @@ -81,7 +81,7 @@ static void afl_forkserver() { while (1) { int status; - u32 was_killed; + unsigned int was_killed; // wait for afl-fuzz if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); From 1dba3a276f40a2496a8726e525a220930fe3d8ba Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Thu, 10 Apr 2025 09:55:19 +0800 Subject: [PATCH 43/61] remove unused variable --- src/afl-cc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index f95216a6..d91b9194 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -187,9 +187,6 @@ typedef struct aflcc_state { u8 need_aflpplib; int passthrough; - u8 use_stdin; /* dummy */ - u8 *argvnull; /* dummy */ - } aflcc_state_t; void aflcc_state_init(aflcc_state_t *, u8 *argv0); From 6691ce943a256e17967d613eca118ed051031f8e Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Thu, 10 Apr 2025 09:55:54 +0800 Subject: [PATCH 44/61] remove unused variable --- src/afl-common.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index 892745a7..059d14d3 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -977,11 +977,10 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { inline u64 get_cur_time(void) { - struct timeval tv; - struct timezone tz; + struct timeval tv; // TO NOT REPLACE WITH clock_gettime!!! - gettimeofday(&tv, &tz); + gettimeofday(&tv, NULL); return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); @@ -991,11 +990,10 @@ inline u64 get_cur_time(void) { inline u64 get_cur_time_us(void) { - struct timeval tv; - struct timezone tz; + struct timeval tv; // TO NOT REPLACE WITH clock_gettime!!! - gettimeofday(&tv, &tz); + gettimeofday(&tv, NULL); return (tv.tv_sec * 1000000ULL) + tv.tv_usec; From b9c153628335c46002cfd8d5ead2001cd8d9fd9a Mon Sep 17 00:00:00 2001 From: w1redch4d Date: Thu, 10 Apr 2025 19:44:54 +0530 Subject: [PATCH 45/61] added safe_length option for portability and clarity --- include/android-ashmem.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 174c655f..ce1558f8 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -30,8 +30,9 @@ int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { int ret = 0; if (__cmd == IPC_RMID) { - unsigned int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); - struct ashmem_pin pin = {0, length}; + int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); + unsigned int safe_length = length >= 0 ? length : 0; + struct ashmem_pin pin = {0, safe_length}; ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); close(__shmid); From 8461f860eb38763160b60c9e712fa47fc914f19a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 10 Apr 2025 16:28:03 +0200 Subject: [PATCH 46/61] code format --- include/afl-fuzz.h | 4 ++-- include/android-ashmem.h | 4 ++-- src/afl-fuzz-queue.c | 46 +++++++++++++++++++++--------------- src/afl-fuzz-state.c | 4 +++- utils/qbdi_mode/template.cpp | 2 +- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 806aecf9..d8ccb20d 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -721,7 +721,7 @@ typedef struct afl_state { struct queue_entry **top_rated; /* Top entries for bitmap bytes */ - u32 **top_rated_candidates; /* Candidate IDs per bitmap index */ + u32 **top_rated_candidates; /* Candidate IDs per bitmap index */ struct extra_data *extras; /* Extra tokens to fuzz with */ u32 extras_cnt; /* Total number of tokens read */ @@ -864,7 +864,7 @@ typedef struct afl_state { struct skipdet_global *skipdet_g; - s64 last_scored_idx; /* Index of the last queue entry re-scored */ + s64 last_scored_idx; /* Index of the last queue entry re-scored */ #ifdef INTROSPECTION char mutation[8072]; diff --git a/include/android-ashmem.h b/include/android-ashmem.h index ce1558f8..8155d35c 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -30,8 +30,8 @@ int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { int ret = 0; if (__cmd == IPC_RMID) { - int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); - unsigned int safe_length = length >= 0 ? length : 0; + int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); + unsigned int safe_length = length >= 0 ? length : 0; struct ashmem_pin pin = {0, safe_length}; ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); close(__shmid); diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 74d35fe5..48c7c454 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -1015,32 +1015,37 @@ void recalculate_all_scores(afl_state_t *afl) { for (j = 0; j < afl->fsrv.map_size; ++j) { - if (afl->fsrv.trace_bits[j]) { + if (afl->fsrv.trace_bits[j]) { u32 *candidate_ids = afl->top_rated_candidates[j]; - u32 id = afl->queue_buf[i]->id; - + u32 id = afl->queue_buf[i]->id; + if (!candidate_ids) { + // first candidate: [count][id] candidate_ids = ck_alloc(sizeof(u32) * 2); - candidate_ids[0] = 1; // count = 1 - candidate_ids[1] = id; // first ID + candidate_ids[0] = 1; // count = 1 + candidate_ids[1] = id; // first ID + } else { + u32 count = candidate_ids[0]; - - candidate_ids = ck_realloc(candidate_ids, sizeof(u32) * (count + 2)); - candidate_ids[0] = count + 1; // increment the count - candidate_ids[count + 1] = id; // append the new ID to the end - - //fprintf(stderr, "enroll candidate[%u][%u] %u\n", i, j, id); + + candidate_ids = + ck_realloc(candidate_ids, sizeof(u32) * (count + 2)); + candidate_ids[0] = count + 1; // increment the count + candidate_ids[count + 1] = id; // append the new ID to the end + + // fprintf(stderr, "enroll candidate[%u][%u] %u\n", i, j, id); + } - + afl->top_rated_candidates[j] = candidate_ids; } + } - - + } afl->last_scored_idx = i; @@ -1050,17 +1055,20 @@ void recalculate_all_scores(afl_state_t *afl) { for (i = 0; i < afl->fsrv.map_size; ++i) { u32 *candidate_ids = afl->top_rated_candidates[i]; - if(candidate_ids) { + if (candidate_ids) { + u32 count = candidate_ids[0]; - for(u32 k = 0; k < count; k++) { - u32 id = candidate_ids[k + 1]; + for (u32 k = 0; k < count; k++) { + + u32 id = candidate_ids[k + 1]; struct queue_entry *entry = afl->queue_buf[id]; update_bitmap_rescore(afl, entry, i); + } - + } - + } } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 83d92080..2415b0b4 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -107,7 +107,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL; afl->q_testcase_max_cache_entries = 64 * 1024; afl->last_scored_idx = -1; - + #ifdef HAVE_AFFINITY afl->cpu_aff = -1; /* Selected CPU core */ #endif /* HAVE_AFFINITY */ @@ -744,7 +744,9 @@ void afl_state_deinit(afl_state_t *afl) { for (u32 i = 0; i < afl->fsrv.map_size; i++) { if (afl->top_rated_candidates[i]) { + ck_free(afl->top_rated_candidates[i]); + } } diff --git a/utils/qbdi_mode/template.cpp b/utils/qbdi_mode/template.cpp index 2f66b3df..903a1ea1 100755 --- a/utils/qbdi_mode/template.cpp +++ b/utils/qbdi_mode/template.cpp @@ -80,7 +80,7 @@ static void afl_forkserver() { while (1) { - int status; + int status; unsigned int was_killed; // wait for afl-fuzz if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); From 57fa87ce5e75b7fef0cf6bfa7af55f99114b9c06 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 12 Apr 2025 09:26:57 +0000 Subject: [PATCH 47/61] only allocate SAND memory if enabled --- src/afl-fuzz.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1170c303..871c3cea 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1756,8 +1756,21 @@ int main(int argc, char **argv_orig, char **envp) { } - afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); - afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); + if (afl->san_binary_length) { + + if (afl->san_abstraction == UNIQUE_TRACE) { + + afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); + + } + + if (afl->san_abstraction == SIMPLIFY_TRACE) { + + afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); + + } + + } if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; } if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; } @@ -3616,6 +3629,10 @@ stop_fuzzing: } + ck_free(afl->n_fuzz); + ck_free(afl->n_fuzz_dup); + ck_free(afl->simplified_n_fuzz); + if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); From 95133973363069033a42d2c4f4c0f0640e9b3d69 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 12 Apr 2025 09:27:59 +0000 Subject: [PATCH 48/61] free memory when shutdown With this fix, ASAN_BUILD won't report leaks if ctrl-c (in a short run). --- src/afl-fuzz-queue.c | 1 + src/afl-fuzz-state.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 48c7c454..a599108f 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -766,6 +766,7 @@ void destroy_queue(afl_state_t *afl) { for (i = 0; i < afl->queued_items; i++) { q = afl->queue_buf[i]; + ck_free(q->testcase_buf); ck_free(q->fname); ck_free(q->trace_mini); if (q->skipdet_e) { diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 2415b0b4..59cc7657 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -773,6 +773,11 @@ void afl_state_deinit(afl_state_t *afl) { ck_free(afl->first_trace); ck_free(afl->map_tmp_buf); + ck_free(afl->skipdet_g->inf_prof); + ck_free(afl->skipdet_g->virgin_det_bits); + ck_free(afl->skipdet_g); + ck_free(afl->havoc_prof); + list_remove(&afl_states, afl); } From 5ed187b517016bbb9265a22633d2323e35736014 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 12 Apr 2025 12:57:37 +0200 Subject: [PATCH 49/61] fix for cycle_schedule change --- src/afl-fuzz-queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index a599108f..faec406d 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -1011,7 +1011,7 @@ void recalculate_all_scores(afl_state_t *afl) { if (likely(!afl->queue_buf[i]->disabled)) { in_buf = queue_testcase_get(afl, afl->queue_buf[i]); - (void)write_to_testcase(afl, in_buf, afl->queue_buf[i]->len, 1); + (void)write_to_testcase(afl, (void **)&in_buf, afl->queue_buf[i]->len, 1); (void)fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); for (j = 0; j < afl->fsrv.map_size; ++j) { From 1d2de1cb6d8790585104c26d7cf0946097e3ad91 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Fri, 11 Apr 2025 02:18:43 +0000 Subject: [PATCH 50/61] remove dead code in comment --- include/afl-fuzz.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index d8ccb20d..4729c321 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1344,7 +1344,6 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed), "/dev/urandom"); - // srandom(afl->rand_seed[0]); afl->rand_cnt = (RESEED_RNG / 2) + (afl->rand_seed[1] % RESEED_RNG); } From dee51213a7aa2f37265eac3db0d03460bd2339dc Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Fri, 11 Apr 2025 02:27:40 +0000 Subject: [PATCH 51/61] update build dependency rule in GNUmakefile --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 9dae4dec..bbe95908 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -490,7 +490,7 @@ ifdef IS_IOS @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } endif -afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 +afl-showmap: src/afl-showmap.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) ifdef IS_IOS @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } From 03169b2b67aca42634306ac36e28e9cd3febbba7 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 12 Apr 2025 05:26:11 +0000 Subject: [PATCH 52/61] print the file name with variable behavior Because queue/.state/variable_behavior was removed, print file name in case some users still want the information. --- src/afl-fuzz-run.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 7dfa7a30..66634513 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -592,11 +592,11 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, // note: from_queue seems to only be set during initialization if (afl->afl_env.afl_no_ui || from_queue) { - WARNF("instability detected during calibration"); + WARNF("instability detected during calibration: %s", q->fname); } else if (afl->debug) { - DEBUGF("instability detected during calibration\n"); + DEBUGF("instability detected during calibration: %s\n", q->fname); } From be8393f201c56f57096f299378aa927de42d3a7b Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 12 Apr 2025 15:38:20 +0000 Subject: [PATCH 53/61] fix in_define in .custom-format.py avoid the extra \ before #define line --- .custom-format.py | 7 +++---- include/xxhash.h | 2 +- src/afl-common.c | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index e787df28..e7e2892b 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -86,9 +86,10 @@ def custom_format(filename): out = "" for line in src.split("\n"): + define_start = False if line.lstrip().startswith("#"): if line[line.find("#") + 1:].lstrip().startswith("define"): - in_define = True + define_start = True if ( "/*" in line @@ -126,9 +127,7 @@ def custom_format(filename): and last_line.strip() != "" ): line = (" " * define_padding + "\\" if in_define else "") + "\n" + line - - if not line.endswith("\\"): - in_define = False + in_define = (define_start or in_define) and line.endswith("\\") out += line + "\n" last_line = line diff --git a/include/xxhash.h b/include/xxhash.h index 72044177..59abd0e9 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -3169,7 +3169,7 @@ static xxh_u32 XXH32_avalanche(xxh_u32 hash) { */ static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8 *ptr, size_t len, XXH_alignment align) { -\ + #define XXH_PROCESS1 \ do { \ \ diff --git a/src/afl-common.c b/src/afl-common.c index 059d14d3..736c9f3d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1004,7 +1004,7 @@ inline 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 { \ \ @@ -1168,7 +1168,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 { \ \ From 4bd492f2126f33156ffea797e3c989759ffc88de Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 12 Apr 2025 16:56:14 +0000 Subject: [PATCH 54/61] fix memory leak in check_main_node_exists --- src/afl-fuzz-init.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index e35ed2a3..cf8d319c 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2227,10 +2227,17 @@ int check_main_node_exists(afl_state_t *afl) { fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name); int res = access(fn, F_OK); free(fn); - if (res == 0) return 1; + if (res == 0) { + + closedir(sd); + return 1; + + } } + closedir(sd); + return 0; } From 0b12c7e0cc5c929c850a4bd583c5b3ac74ee2175 Mon Sep 17 00:00:00 2001 From: r3st <104332533+r3sting@users.noreply.github.com> Date: Sat, 12 Apr 2025 16:20:33 -0600 Subject: [PATCH 55/61] Fix linker error --- qemu_mode/README.deferred_initialization_example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu_mode/README.deferred_initialization_example.md b/qemu_mode/README.deferred_initialization_example.md index d940d6b5..30fe1932 100644 --- a/qemu_mode/README.deferred_initialization_example.md +++ b/qemu_mode/README.deferred_initialization_example.md @@ -40,7 +40,7 @@ ALPINE_ROOT= FUZZ= sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /fuzz -clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c +clang $(python3-config --embed --cflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c $(python3-config --embed --ldflags) exit ``` From e305bc15d359e7117d218306ea3ef07792c59223 Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sun, 13 Apr 2025 03:06:06 +0000 Subject: [PATCH 56/61] fix memory leaks --- src/afl-fuzz-run.c | 9 ++++++++- src/afl-fuzz-state.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 66634513..e6fb3ac6 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -867,7 +867,14 @@ void sync_fuzzers(afl_state_t *afl) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); - if (afl->stop_soon) { goto close_sync; } + if (afl->stop_soon) { + + munmap(mem, st.st_size); + close(fd); + + goto close_sync; + + } afl->syncing_party = sd_ent->d_name; afl->queued_imported += save_if_interesting(afl, mem, new_len, fault); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 59cc7657..67a3f31d 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -762,6 +762,8 @@ void afl_state_deinit(afl_state_t *afl) { afl_free(afl->in_buf); afl_free(afl->in_scratch_buf); afl_free(afl->ex_buf); + afl_free(afl->alias_table); + afl_free(afl->alias_probability); ck_free(afl->virgin_bits); ck_free(afl->virgin_tmout); From 5b9d2cc38b45fe24a6b02a020202d1015d2e274d Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sun, 13 Apr 2025 08:23:20 +0000 Subject: [PATCH 57/61] code-format cache This change reduces "make code-format" from 3 minutes to 3 seconds if large files are not changed. --- .custom-format.py | 39 ++++++++++++++++++++++++++++++++++++++- .gitignore | 3 ++- GNUmakefile | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index e787df28..37172687 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -21,12 +21,15 @@ import os # import re # TODO: for future use import shutil import importlib.metadata +import hashlib # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use CURRENT_LLVM = os.getenv('LLVM_VERSION', 18) CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") +FORMAT_CACHE_DIR = '.format-cache' +os.makedirs(FORMAT_CACHE_DIR, exist_ok=True) def check_clang_format_pip_version(): """ @@ -69,6 +72,8 @@ to install via pip.") if CLANG_FORMAT_PIP: CLANG_FORMAT_BIN = shutil.which("clang-format") +CLANG_FORMAT_VERSION = subprocess.check_output([CLANG_FORMAT_BIN, '--version']) + COLUMN_LIMIT = 80 for line in fmt.split("\n"): line = line.split(":") @@ -136,6 +141,38 @@ def custom_format(filename): return out +def hash_code_and_formatter(code): + hasher = hashlib.sha256() + + hasher.update(code.encode()) + hasher.update(CLANG_FORMAT_VERSION) + with open(__file__, 'rb') as f: + hasher.update(f.read()) + + return hasher.hexdigest() + + +def custom_format_cached(filename): + filename_hash = hashlib.sha256(filename.encode()).hexdigest() + cache_file = os.path.join(FORMAT_CACHE_DIR, filename_hash) + + if os.path.exists(cache_file): + with open(filename) as f: + code = f.read() + code_hash = hash_code_and_formatter(code) + with open(cache_file) as f: + if f.read() == code_hash: + return code + + code = custom_format(filename) + + code_hash = hash_code_and_formatter(code) + with open(cache_file, 'w') as f: + f.write(code_hash) + + return code + + args = sys.argv[1:] if len(args) == 0: print("Usage: ./format.py [-i] ") @@ -151,7 +188,7 @@ if args[0] == "-i": args = args[1:] for filename in args: - code = custom_format(filename) + code = custom_format_cached(filename) if in_place: with open(filename, "w") as f: f.write(code) diff --git a/.gitignore b/.gitignore index bc06ef2d..4f25e5e4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.so *.swp .DS_Store +.format-cache .sync_tmp .test .test2 @@ -113,4 +114,4 @@ utils/replay_record/persistent_demo_replay_argparse utils/plot_ui/afl-plot-ui vuln_prog argv_fuzz_demo -argv_fuzz_persistent_demo \ No newline at end of file +argv_fuzz_persistent_demo diff --git a/GNUmakefile b/GNUmakefile index bbe95908..697c48af 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -684,6 +684,7 @@ deepclean: clean rm -rf unicorn_mode/unicornafl rm -rf qemu_mode/qemuafl rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx + rm -rf .format-cache ifeq "$(IN_REPO)" "1" git checkout coresight_mode/coresight-trace git checkout unicorn_mode/unicornafl From 7f2becba72001c699a319a42c80328d1b51b4471 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 14 Apr 2025 13:57:45 +0200 Subject: [PATCH 58/61] build fix for asan+performance --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 697c48af..99aebced 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -473,7 +473,7 @@ ready: @echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))" src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h - $(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o + $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o From 05dfb7078753f2c7e21a292e93c4ebadfe3c609d Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Wed, 16 Apr 2025 00:48:02 +0000 Subject: [PATCH 59/61] fix build for "make PERFORMANCE=1 unit" --- GNUmakefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 99aebced..7fac85ad 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -535,20 +535,20 @@ ifdef IS_IOS endif test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o - @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o + @$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o unit_hash: test/unittests/unit_hash.o src/afl-performance.o - @$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka ./test/unittests/unit_hash ifdef IS_IOS @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } endif test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o - @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o + @$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o - @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka ./test/unittests/unit_rand ifdef IS_IOS @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } From 0d286c9e19f7718a811647ab5321bfad8047ef79 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 16 Apr 2025 12:07:39 +0100 Subject: [PATCH 60/61] build: improve lld version parsing Currently, if LLD is in a weird location and has a version string like: ```bash Ubuntu LLD 18.1.3 (compatible with GNU linkers) ``` or ```bash Homebrew LLD 20.1.2 (compatible with GNU linkers) ``` The version comparison will fail: ```bash GNUmakefile.llvm:247: ld.lld found in a weird location (/opt/homebrew/bin/ld.lld) and its of a different version than LLMV (LLD vs. 20.1.2) - cannot enable LTO mode ``` Fix that by replacing the usage of awk, with the same sed command used to retrieve the version of Clang, which fixes the issue: ```bash GNUmakefile.llvm:245: ld.lld found in a weird location (/opt/homebrew/bin/ld.lld), but its the same version as LLVM so we will allow it ``` --- GNUmakefile.llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 653d3b68..73ec7cf7 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -240,7 +240,7 @@ ifeq "$(LLVM_LTO)" "1" else ifneq "$(shell command -v ld.lld 2>/dev/null)" "" AFL_REAL_LD = $(shell command -v ld.lld) - TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }') + TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | sed -E -ne '/^.*LLD\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p') ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)" $(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it) else From 20a6cdabad2ce39a886a1bfe1c1f12b559738cd9 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 16 Apr 2025 14:03:26 +0100 Subject: [PATCH 61/61] ci: drop usage of ubuntu:20.04 Support for this has been removed by GitHub: https://github.com/actions/runner-images/issues/11101. --- .github/workflows/rust_custom_mutator.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust_custom_mutator.yml b/.github/workflows/rust_custom_mutator.yml index 7c2f0c12..f5c16a1e 100644 --- a/.github/workflows/rust_custom_mutator.yml +++ b/.github/workflows/rust_custom_mutator.yml @@ -18,7 +18,7 @@ jobs: working-directory: custom_mutators/rust strategy: matrix: - os: [ubuntu-22.04, ubuntu-20.04] + os: [ubuntu-22.04] steps: - uses: actions/checkout@v3 - name: Install Rust Toolchain