Merge branch 'AFLplusplus:stable' into stable

This commit is contained in:
Toki 2025-04-17 15:20:31 +02:00 committed by GitHub
commit fa8dc2028f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 669 additions and 368 deletions

View File

@ -21,12 +21,15 @@ import os
# import re # TODO: for future use # import re # TODO: for future use
import shutil import shutil
import importlib.metadata import importlib.metadata
import hashlib
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18) CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") 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(): def check_clang_format_pip_version():
""" """
@ -69,6 +72,8 @@ to install via pip.")
if CLANG_FORMAT_PIP: if CLANG_FORMAT_PIP:
CLANG_FORMAT_BIN = shutil.which("clang-format") CLANG_FORMAT_BIN = shutil.which("clang-format")
CLANG_FORMAT_VERSION = subprocess.check_output([CLANG_FORMAT_BIN, '--version'])
COLUMN_LIMIT = 80 COLUMN_LIMIT = 80
for line in fmt.split("\n"): for line in fmt.split("\n"):
line = line.split(":") line = line.split(":")
@ -86,9 +91,10 @@ def custom_format(filename):
out = "" out = ""
for line in src.split("\n"): for line in src.split("\n"):
define_start = False
if line.lstrip().startswith("#"): if line.lstrip().startswith("#"):
if line[line.find("#") + 1:].lstrip().startswith("define"): if line[line.find("#") + 1:].lstrip().startswith("define"):
in_define = True define_start = True
if ( if (
"/*" in line "/*" in line
@ -126,9 +132,7 @@ def custom_format(filename):
and last_line.strip() != "" and last_line.strip() != ""
): ):
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
in_define = (define_start or in_define) and line.endswith("\\")
if not line.endswith("\\"):
in_define = False
out += line + "\n" out += line + "\n"
last_line = line last_line = line
@ -136,6 +140,38 @@ def custom_format(filename):
return out 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:] args = sys.argv[1:]
if len(args) == 0: if len(args) == 0:
print("Usage: ./format.py [-i] <filename>") print("Usage: ./format.py [-i] <filename>")
@ -151,7 +187,7 @@ if args[0] == "-i":
args = args[1:] args = args[1:]
for filename in args: for filename in args:
code = custom_format(filename) code = custom_format_cached(filename)
if in_place: if in_place:
with open(filename, "w") as f: with open(filename, "w") as f:
f.write(code) f.write(code)

View File

@ -18,7 +18,7 @@ jobs:
working-directory: custom_mutators/rust working-directory: custom_mutators/rust
strategy: strategy:
matrix: matrix:
os: [ubuntu-22.04, ubuntu-20.04] os: [ubuntu-22.04]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Rust Toolchain - name: Install Rust Toolchain

1
.gitignore vendored
View File

@ -7,6 +7,7 @@
*.so *.so
*.swp *.swp
.DS_Store .DS_Store
.format-cache
.sync_tmp .sync_tmp
.test .test
.test2 .test2

View File

@ -473,7 +473,7 @@ ready:
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))" @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 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 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 $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
@ -490,7 +490,7 @@ ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif 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) $(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 ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
@ -535,20 +535,20 @@ ifdef IS_IOS
endif endif
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o 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 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 ./test/unittests/unit_hash
ifdef IS_IOS ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif endif
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o 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 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 ./test/unittests/unit_rand
ifdef IS_IOS ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; } @ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
@ -684,6 +684,7 @@ deepclean: clean
rm -rf unicorn_mode/unicornafl rm -rf unicorn_mode/unicornafl
rm -rf qemu_mode/qemuafl rm -rf qemu_mode/qemuafl
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
rm -rf .format-cache
ifeq "$(IN_REPO)" "1" ifeq "$(IN_REPO)" "1"
git checkout coresight_mode/coresight-trace git checkout coresight_mode/coresight-trace
git checkout unicorn_mode/unicornafl git checkout unicorn_mode/unicornafl

View File

@ -240,7 +240,7 @@ ifeq "$(LLVM_LTO)" "1"
else else
ifneq "$(shell command -v ld.lld 2>/dev/null)" "" ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
AFL_REAL_LD = $(shell command -v ld.lld) 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)" 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) $(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
else else

View File

@ -432,7 +432,7 @@ BEGIN {
} else { } else {
stat_format = "-f '%z %N'" # *BSD, MacOS 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 \\) -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 = "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" && stat "stat_format" *) | sort -k1n -k2r"
#cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r" #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"

View File

@ -121,6 +121,7 @@ kernel.sched_child_runs_first=1
kernel.sched_autogroup_enabled=1 kernel.sched_autogroup_enabled=1
kernel.sched_migration_cost_ns=50000000 kernel.sched_migration_cost_ns=50000000
kernel.sched_latency_ns=250000000 kernel.sched_latency_ns=250000000
vm.swappiness=10
EOF EOF
} }
@ -129,7 +130,7 @@ EOF
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
echo "Configuring performance boot options" echo "Configuring performance boot options"
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'` 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\" echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
fi fi

View File

@ -41,6 +41,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
sysctl -w kernel.sched_autogroup_enabled=1 sysctl -w kernel.sched_autogroup_enabled=1
sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null
sysctl -w kernel.sched_latency_ns=250000000 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 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/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 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 echo
dmesg | grep -E -q 'noibrs pcid nopti' || { 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 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
} }
echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed. echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.

View File

@ -6,6 +6,14 @@
### Version ++4.32a (dev) ### Version ++4.32a (dev)
- Fixed a bug where after a fast restart of a full fuzzed corpus afl-fuzz - 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" 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!
- 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
### Version ++4.31c (release) ### Version ++4.31c (release)

View File

@ -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 [AFLFast](https://github.com/mboehme/aflfast), however, modified to be more
effective and several more modes added. 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 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 to assign a different schedule to each instance, however the majority should

View File

@ -385,10 +385,6 @@ there are several things to look at:
subsequent iterations (e.g., due to incomplete clean-up or reinitialization of 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 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 `<out_dir>/queue/.state/variable_behavior/` directory, so you can look
them up easily.
### CPU load ### CPU load
``` ```

View File

@ -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 target (which means more instances can be run without a sanitized target, which
is more effective). 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 ### d) Modifying the target
If the target has features that make fuzzing more difficult, e.g., checksums, If the target has features that make fuzzing more difficult, e.g., checksums,
@ -496,6 +502,8 @@ Note:
protection against attacks! So set strong firewall rules and only expose SSH protection against attacks! So set strong firewall rules and only expose SSH
as a network service if you use these (which is highly recommended). 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), 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 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. directory and create a file with any content as test data in there.

View File

@ -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_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)" GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
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)"; \ IS_GUM_16_6_PLUS := $(shell VERSION="$(GUM_DEVKIT_VERSION)"; \
MAJOR=$${VERSION%%.*}; \ MAJOR=$${VERSION%%.*}; \
MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \ MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \
if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \ if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \
echo 1; \ echo 1; \
fi) fi)
endif
CFLAGS += $(if $(IS_GUM_16_6_PLUS),-DGUM_16_6_PLUS) CFLAGS += $(if $(IS_GUM_16_6_PLUS),-DGUM_16_6_PLUS)

View File

@ -28,8 +28,7 @@ void asan_init(void) {
} }
#ifdef GUM_16_6_PLUS #ifdef GUM_16_6_PLUS
static gboolean asan_exclude_module(GumModule *module, static gboolean asan_exclude_module(GumModule *module, gpointer user_data) {
gpointer user_data) {
gchar *symbol_name = (gchar *)user_data; gchar *symbol_name = (gchar *)user_data;
GumAddress address; GumAddress address;
@ -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 /* If the reported address of the symbol is outside of the range of the module
* then ignore it */ * then ignore it */
if (address < range->base_address) { return TRUE; } if (address < range->base_address) { return TRUE; }
if (address > (range->base_address + range->size)) { if (address > (range->base_address + range->size)) { return TRUE; }
return TRUE;
}
ranges_add_exclude((GumMemoryRange *)range); ranges_add_exclude((GumMemoryRange *)range);
return FALSE; return FALSE;
} }
#else #else
static gboolean asan_exclude_module(const GumModuleDetails *details, static gboolean asan_exclude_module(const GumModuleDetails *details,
gpointer user_data) { gpointer user_data) {
@ -72,6 +70,7 @@ static gboolean asan_exclude_module(const GumModuleDetails *details,
return FALSE; return FALSE;
} }
#endif #endif
void asan_exclude_module_by_symbol(gchar *symbol_name) { 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); gum_process_enumerate_modules(asan_exclude_module, symbol_name);
} }

View File

@ -40,8 +40,7 @@ static guint64 text_base = 0;
static guint64 text_limit = 0; static guint64 text_limit = 0;
#ifdef GUM_16_6_PLUS #ifdef GUM_16_6_PLUS
static gboolean lib_find_exe(GumModule *module, static gboolean lib_find_exe(GumModule *module, gpointer user_data) {
gpointer user_data) {
lib_details_t *lib_details = (lib_details_t *)user_data; lib_details_t *lib_details = (lib_details_t *)user_data;
const gchar *name = gum_module_get_name(module); const gchar *name = gum_module_get_name(module);
@ -57,6 +56,7 @@ static gboolean lib_find_exe(GumModule *module,
return FALSE; return FALSE;
} }
#else #else
static gboolean lib_find_exe(const GumModuleDetails *details, static gboolean lib_find_exe(const GumModuleDetails *details,
gpointer user_data) { gpointer user_data) {
@ -72,6 +72,7 @@ static gboolean lib_find_exe(const GumModuleDetails *details,
return FALSE; return FALSE;
} }
#endif #endif
static void lib_validate_hdr(Elf_Ehdr *hdr) { static void lib_validate_hdr(Elf_Ehdr *hdr) {
@ -210,3 +211,4 @@ guint64 lib_get_text_limit(void) {
} }
#endif #endif

View File

@ -13,15 +13,14 @@ static guint64 text_base = 0;
static guint64 text_limit = 0; static guint64 text_limit = 0;
#ifdef GUM_16_6_PLUS #ifdef GUM_16_6_PLUS
static gboolean lib_get_main_module(GumModule *module, static gboolean lib_get_main_module(GumModule *module, gpointer user_data) {
gpointer user_data) {
GumDarwinModule **ret = (GumDarwinModule **)user_data; GumDarwinModule **ret = (GumDarwinModule **)user_data;
const gchar *path = gum_module_get_path(module); const gchar *path = gum_module_get_path(module);
const GumMemoryRange *range = gum_module_get_range(module); const GumMemoryRange *range = gum_module_get_range(module);
GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory( GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory(
path, mach_task_self(), range->base_address, path, mach_task_self(), range->base_address, GUM_DARWIN_MODULE_FLAGS_NONE,
GUM_DARWIN_MODULE_FLAGS_NONE, NULL); NULL);
FVERBOSE("Found main module: %s", darwin_module->name); FVERBOSE("Found main module: %s", darwin_module->name);
@ -30,6 +29,7 @@ static gboolean lib_get_main_module(GumModule *module,
return FALSE; return FALSE;
} }
#else #else
static gboolean lib_get_main_module(const GumModuleDetails *details, static gboolean lib_get_main_module(const GumModuleDetails *details,
gpointer user_data) { gpointer user_data) {
@ -46,6 +46,7 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
return FALSE; return FALSE;
} }
#endif #endif
gboolean lib_get_text_section(const GumDarwinSectionDetails *details, gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
@ -105,3 +106,4 @@ guint64 lib_get_text_limit(void) {
} }
#endif #endif

View File

@ -262,6 +262,7 @@ static int prefetch_on_fork(void) {
} }
static void prefetch_hook_fork(void) { static void prefetch_hook_fork(void) {
#ifdef GUM_16_6_PLUS #ifdef GUM_16_6_PLUS
void *fork_addr = void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_global_export_by_name("fork")); 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; iface->notify_backpatch = gum_afl_stalker_backpatcher_notify;
} }

View File

@ -129,14 +129,15 @@ static gboolean convert_name_token_for_module(GumModule *module,
FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x %s", "x-0x%016" G_GINT64_MODIFIER "x %s",
ctx->suffix, range->base_address, ctx->suffix, range->base_address, range->base_address + range->size,
range->base_address + range->size, path); path);
*ctx->range = *range; *ctx->range = *range;
ctx->done = true; ctx->done = true;
return false; return false;
} }
#else #else
static gboolean convert_name_token_for_module(const GumModuleDetails *details, static gboolean convert_name_token_for_module(const GumModuleDetails *details,
gpointer user_data) { gpointer user_data) {
@ -156,6 +157,7 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details,
return false; return false;
} }
#endif #endif
static void convert_name_token(gchar *token, GumMemoryRange *range) { static void convert_name_token(gchar *token, GumMemoryRange *range) {
@ -736,3 +738,4 @@ void ranges_exclude() {
} }
} }

View File

@ -353,6 +353,8 @@ enum {
}; };
#define FAST_RESUME_VERSION 0x01000000
/* Python stuff */ /* Python stuff */
#ifdef USE_PYTHON #ifdef USE_PYTHON
@ -719,6 +721,8 @@ typedef struct afl_state {
struct queue_entry **top_rated; /* Top entries for bitmap bytes */ 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 */ struct extra_data *extras; /* Extra tokens to fuzz with */
u32 extras_cnt; /* Total number of tokens read */ u32 extras_cnt; /* Total number of tokens read */
@ -860,6 +864,8 @@ typedef struct afl_state {
struct skipdet_global *skipdet_g; struct skipdet_global *skipdet_g;
s64 last_scored_idx; /* Index of the last queue entry re-scored */
#ifdef INTROSPECTION #ifdef INTROSPECTION
char mutation[8072]; char mutation[8072];
char m_tmp[4096]; char m_tmp[4096];
@ -1182,13 +1188,13 @@ void deinit_py(void *);
/* Queue */ /* Queue */
void mark_as_det_done(afl_state_t *, struct queue_entry *); 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 add_to_queue(afl_state_t *, u8 *, u32, u8);
void destroy_queue(afl_state_t *); 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 *); void cull_queue(afl_state_t *);
u32 calculate_score(afl_state_t *, struct queue_entry *); 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 */ /* Bitmap */
@ -1338,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), ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
"/dev/urandom"); "/dev/urandom");
// srandom(afl->rand_seed[0]);
afl->rand_cnt = (RESEED_RNG / 2) + (afl->rand_seed[1] % RESEED_RNG); afl->rand_cnt = (RESEED_RNG / 2) + (afl->rand_seed[1] % RESEED_RNG);
} }
@ -1452,6 +1457,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 #if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1 #error define of TESTCASE_CACHE must be zero or larger than 1
#endif #endif

View File

@ -31,7 +31,8 @@ int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
if (__cmd == IPC_RMID) { if (__cmd == IPC_RMID) {
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
struct ashmem_pin pin = {0, length}; unsigned int safe_length = length >= 0 ? length : 0;
struct ashmem_pin pin = {0, safe_length};
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
close(__shmid); close(__shmid);

View File

@ -37,11 +37,12 @@
enum SanitizerAbstraction { enum SanitizerAbstraction {
SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate
// most sensitive // sensitive and default for SAND. Not missing bugs.
UNIQUE_TRACE, 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 COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the
// least sensitive // least sensitive at a risk of missing ~20% bugs.
}; };

View File

@ -171,7 +171,8 @@
#define EXEC_TM_ROUND 20U #define EXEC_TM_ROUND 20U
/* 64bit arch MACRO */ /* 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 #define WORD_SIZE_64 1
#endif #endif
@ -200,8 +201,8 @@
/* Maximum number of unique hangs or crashes to record: */ /* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500U #define KEEP_UNIQUE_HANG 512U
#define KEEP_UNIQUE_CRASH 10000U #define KEEP_UNIQUE_CRASH 25600U
/* Baseline number of random tweaks during a single 'havoc' stage: */ /* Baseline number of random tweaks during a single 'havoc' stage: */

View File

@ -9,7 +9,6 @@
u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end); u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end);
u32 classify_word(u32 word); u32 classify_word(u32 word);
void classify_counts_mem(u32 *mem, u32 size);
inline u32 classify_word(u32 word) { 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) { void simplify_trace(afl_state_t *afl, u8 *bytes) {
u32 *mem = (u32 *)bytes; u32 *mem = (u32 *)bytes;

View File

@ -13,7 +13,6 @@
u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end); u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end);
u64 classify_word(u64 word); u64 classify_word(u64 word);
void classify_counts_mem(u64 *mem, u32 size);
inline u64 classify_word(u64 word) { inline u64 classify_word(u64 word) {
@ -79,22 +78,6 @@ inline void classify_counts(afl_forkserver_t *fsrv) {
} }
inline void classify_counts_mem(u64 *mem, u32 size) {
u32 i = (size >> 3);
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 /* Updates the virgin bits, then reflects whether a new count or a new tuple is
* seen in ret. */ * seen in ret. */
inline void discover_word(u8 *ret, u64 *current, u64 *virgin) { inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {

View File

@ -137,6 +137,8 @@ typedef struct afl_forkserver {
u8 last_kill_signal; /* Signal that killed the child */ 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 use_shmem_fuzz; /* use shared mem for test cases */
bool support_shmem_fuzz; /* set by afl-fuzz */ 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 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? */ bool debug; /* debug mode? */

View File

@ -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, static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8 *ptr,
size_t len, XXH_alignment align) { size_t len, XXH_alignment align) {
\
#define XXH_PROCESS1 \ #define XXH_PROCESS1 \
do { \ do { \
\ \

View File

@ -40,7 +40,7 @@ ALPINE_ROOT=<your-alpine-sysroot-directory>
FUZZ=<your-path-to-the-code> FUZZ=<your-path-to-the-code>
sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz
CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /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 exit
``` ```

View File

@ -187,9 +187,6 @@ typedef struct aflcc_state {
u8 need_aflpplib; u8 need_aflpplib;
int passthrough; int passthrough;
u8 use_stdin; /* dummy */
u8 *argvnull; /* dummy */
} aflcc_state_t; } aflcc_state_t;
void aflcc_state_init(aflcc_state_t *, u8 *argv0); void aflcc_state_init(aflcc_state_t *, u8 *argv0);
@ -2033,8 +2030,10 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
} }
if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) { if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) {
insert_param(aflcc, "-fsanitize=realtime"); insert_param(aflcc, "-fsanitize=realtime");
aflcc->have_rtsan = 1; aflcc->have_rtsan = 1;
} }
if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) {

View File

@ -978,10 +978,9 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
inline u64 get_cur_time(void) { inline u64 get_cur_time(void) {
struct timeval tv; struct timeval tv;
struct timezone tz;
// TO NOT REPLACE WITH clock_gettime!!! // TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz); gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
@ -992,10 +991,9 @@ inline u64 get_cur_time(void) {
inline u64 get_cur_time_us(void) { inline u64 get_cur_time_us(void) {
struct timeval tv; struct timeval tv;
struct timezone tz;
// TO NOT REPLACE WITH clock_gettime!!! // TO NOT REPLACE WITH clock_gettime!!!
gettimeofday(&tv, &tz); gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000ULL) + tv.tv_usec; return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
@ -1006,7 +1004,7 @@ inline u64 get_cur_time_us(void) {
Will return buf for convenience. */ Will return buf for convenience. */
u8 *stringify_int(u8 *buf, size_t len, u64 val) { u8 *stringify_int(u8 *buf, size_t len, u64 val) {
\
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
do { \ do { \
\ \
@ -1170,7 +1168,7 @@ u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
Will return buf for convenience. */ Will return buf for convenience. */
u8 *u_stringify_int(u8 *buf, u64 val) { u8 *u_stringify_int(u8 *buf, u64 val) {
\
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \ #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
do { \ do { \
\ \

View File

@ -258,7 +258,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->last_run_timed_out = false; fsrv->last_run_timed_out = false;
fsrv->debug = false; fsrv->debug = false;
fsrv->uses_crash_exitcode = false; fsrv->uses_crash_exitcode = false;
fsrv->uses_asan = false; fsrv->uses_asan = 0;
#ifdef __AFL_CODE_COVERAGE #ifdef __AFL_CODE_COVERAGE
fsrv->persistent_trace_bits = NULL; fsrv->persistent_trace_bits = NULL;
@ -2087,17 +2087,19 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
/* Did we crash? /* Did we crash?
In a normal case, (abort) WIFSIGNALED(child_status) will be set. 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. 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( if (unlikely(
/* A normal crash/abort */ /* A normal crash/abort */
(WIFSIGNALED(fsrv->child_status)) || (WIFSIGNALED(fsrv->child_status)) ||
/* special handling for msan and lsan */ /* special handling for msan */
(fsrv->uses_asan && ((fsrv->uses_asan & 4) &&
(WEXITSTATUS(fsrv->child_status) == MSAN_ERROR || WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) || /* special handling for lsan */
((fsrv->uses_asan & 2) &&
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR) ||
/* the custom crash_exitcode was returned by the target */ /* the custom crash_exitcode was returned by the target */
(fsrv->uses_crash_exitcode && (fsrv->uses_crash_exitcode &&
WEXITSTATUS(fsrv->child_status) == fsrv->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 = fsrv->last_kill_signal =
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0; 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 #ifdef AFL_PERSISTENT_RECORD
if (unlikely(fsrv->persistent_record)) { if (unlikely(fsrv->persistent_record)) {

View File

@ -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, /* 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 save or queue the input test case for further analysis if so. Returns 1 if
entry is saved, 0 otherwise. */ entry is saved, 0 otherwise. */
@ -481,6 +469,8 @@ static inline u8 bitmap_read(u8 *map, u32 index) {
u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
u32 len, u8 fault) { u32 len, u8 fault) {
u8 classified = 0;
if (unlikely(len == 0)) { return 0; } if (unlikely(len == 0)) { return 0; }
if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
@ -489,6 +479,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
classify_counts(&afl->fsrv); classify_counts(&afl->fsrv);
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
classified = 1;
// Saturated increment // Saturated increment
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
@ -502,8 +493,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
u8 fn[PATH_MAX]; u8 fn[PATH_MAX];
u8 *queue_fn = ""; u8 *queue_fn = "";
u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0, u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1;
need_hash = 1;
s32 fd; s32 fd;
u64 cksum = 0; u64 cksum = 0;
u32 cksum_simplified = 0, cksum_unique = 0; u32 cksum_simplified = 0, cksum_unique = 0;
@ -520,7 +510,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv); classify_counts(&afl->fsrv);
classified = 1;
need_hash = 0; need_hash = 0;
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@ -539,8 +528,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits, memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits,
afl->fsrv.map_size); 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); simplify_trace(afl, afl->san_fsrvs[0].trace_bits);
// Note: Original SAND implementation used XXHASH32 // Note: Original SAND implementation used XXHASH32
@ -569,6 +556,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->san_binary_length) && if (unlikely(afl->san_binary_length) &&
likely(afl->san_abstraction == UNIQUE_TRACE)) { 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 = cksum_unique =
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) && if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) &&
@ -631,10 +628,19 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
/* If we are in coverage increasing abstraction and have fed input to /* If we are in coverage increasing abstraction and have fed input to
sanitizers, we are sure it has new bits.*/ 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); new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
} }
}
if (likely(!new_bits)) { if (likely(!new_bits)) {
if (san_fault == FSRV_RUN_OK) { if (san_fault == FSRV_RUN_OK) {
@ -646,7 +652,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
afl->san_case_status |= NON_COV_INCREASE_BUG; afl->san_case_status |= NON_COV_INCREASE_BUG;
fault = san_fault; fault = san_fault;
classified = new_bits;
goto may_save_fault; goto may_save_fault;
} }
@ -654,7 +659,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
} }
fault = san_fault; fault = san_fault;
classified = new_bits;
save_to_queue: save_to_queue:
@ -799,13 +803,6 @@ may_save_fault:
if (likely(!afl->non_instrumented_mode)) { if (likely(!afl->non_instrumented_mode)) {
if (unlikely(!classified)) {
classify_counts(&afl->fsrv);
classified = 1;
}
simplify_trace(afl, afl->fsrv.trace_bits); simplify_trace(afl, afl->fsrv.trace_bits);
if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; } if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; }
@ -939,13 +936,6 @@ may_save_fault:
if (likely(!afl->non_instrumented_mode)) { if (likely(!afl->non_instrumented_mode)) {
if (unlikely(!classified)) {
classify_counts(&afl->fsrv);
classified = 1;
}
simplify_trace(afl, afl->fsrv.trace_bits); simplify_trace(afl, afl->fsrv.trace_bits);
if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; } if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; }

View File

@ -354,6 +354,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
"Extra '%s' is too big (%s, limit is %s)", fn, "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[0], sizeof(val_bufs[0]), st.st_size),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
ck_free(fn);
continue; continue;
} }
@ -742,10 +743,8 @@ void save_auto(afl_state_t *afl) {
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
u8 *fn = alloc_printf( u8 *fn =
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i, alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
s32 fd; s32 fd;

View File

@ -567,6 +567,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
} }
free(nl);
continue; 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 (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) {
if (first) PFATAL("Unable to access '%s'", fn2); if (first) PFATAL("Unable to access '%s'", fn2);
ck_free(fn2);
continue; 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 // as this could add duplicates of the startup input corpus
int fd = open(fn2, O_RDONLY); int fd = open(fn2, O_RDONLY);
if (fd < 0) {
ck_free(fn2); ck_free(fn2);
continue;
} if (fd < 0) { continue; }
u8 fault; u8 fault;
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem == MAP_FAILED) { if (mem == MAP_FAILED) {
ck_free(fn2); close(fd);
continue; continue;
} }
@ -668,7 +667,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
} }
if (mtime_max > afl->foreign_syncs[iter].mtime) {
afl->foreign_syncs[iter].mtime = mtime_max; afl->foreign_syncs[iter].mtime = mtime_max;
}
free(nl); /* not tracked */ free(nl); /* not tracked */
} }
@ -749,8 +753,6 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
} }
// if (getenv("MYTEST")) afl->in_place_resume = 1;
if (nl_cnt) { if (nl_cnt) {
u32 done = 0; u32 done = 0;
@ -1042,6 +1044,47 @@ void perform_dry_run(afl_state_t *afl) {
if (afl->crash_mode) { break; } 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) { if (afl->fsrv.mem_limit) {
u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
@ -1056,6 +1099,7 @@ void perform_dry_run(afl_state_t *afl) {
" so, please remove it. The fuzzer should be seeded with " " so, please remove it. The fuzzer should be seeded with "
"interesting\n" "interesting\n"
" inputs - but not ones that cause an outright crash.\n\n" " inputs - but not ones that cause an outright crash.\n\n"
"%s"
" - The current memory limit (%s) is too low for this " " - The current memory limit (%s) is too low for this "
"program, causing\n" "program, causing\n"
@ -1085,6 +1129,7 @@ void perform_dry_run(afl_state_t *afl) {
"other options\n" "other options\n"
" fail, poke the Awesome Fuzzing Discord for " " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n", "troubleshooting tips.\n",
msg_exit_code,
stringify_mem_size(val_buf, sizeof(val_buf), stringify_mem_size(val_buf, sizeof(val_buf),
afl->fsrv.mem_limit << 20), afl->fsrv.mem_limit << 20),
afl->fsrv.mem_limit - 1); afl->fsrv.mem_limit - 1);
@ -1101,6 +1146,7 @@ void perform_dry_run(afl_state_t *afl) {
" so, please remove it. The fuzzer should be seeded with " " so, please remove it. The fuzzer should be seeded with "
"interesting\n" "interesting\n"
" inputs - but not ones that cause an outright crash.\n\n" " inputs - but not ones that cause an outright crash.\n\n"
"%s"
" - In QEMU persistent mode the selected address(es) for the " " - In QEMU persistent mode the selected address(es) for the "
"loop are not\n" "loop are not\n"
@ -1113,7 +1159,8 @@ void perform_dry_run(afl_state_t *afl) {
" - Least likely, there is a horrible bug in the fuzzer. If " " - Least likely, there is a horrible bug in the fuzzer. If "
"other options\n" "other options\n"
" fail, poke the Awesome Fuzzing Discord for " " fail, poke the Awesome Fuzzing Discord for "
"troubleshooting tips.\n"); "troubleshooting tips.\n",
msg_exit_code);
} }
@ -2180,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); fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name);
int res = access(fn, F_OK); int res = access(fn, F_OK);
free(fn); free(fn);
if (res == 0) return 1; if (res == 0) {
closedir(sd);
return 1;
} }
}
closedir(sd);
return 0; return 0;
} }
@ -2267,18 +2321,6 @@ void setup_dirs_fds(afl_state_t *afl) {
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(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. */ /* Sync directory for keeping track of cooperating fuzzers. */
if (afl->sync_id) { if (afl->sync_id) {
@ -2601,7 +2643,7 @@ void check_cpu_governor(afl_state_t *afl) {
" afl-fuzz. To keep things moving, run these commands as root:\n\n" " afl-fuzz. To keep things moving, run these commands as root:\n\n"
" cd /sys/devices/system/cpu\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 " " You can later go back to the original state by replacing "
"'performance'\n" "'performance'\n"
@ -3118,11 +3160,23 @@ void check_binary(afl_state_t *afl, u8 *fname) {
} }
if (afl_memmem(f_data, f_len, "__asan_init", 11) || afl->fsrv.uses_asan = 0;
afl_memmem(f_data, f_len, "__msan_init", 11) ||
afl_memmem(f_data, f_len, "__lsan_init", 11)) {
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;
} }

View File

@ -636,7 +636,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
q->len = out_len; q->len = out_len;
memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size); memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size);
update_bitmap_score(afl, q); update_bitmap_score(afl, q, true);
} }

View File

@ -634,7 +634,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_cur_byte = afl->stage_cur >> 3; 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; } 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; 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; } 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; 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; } 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; 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; } 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++) { 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... */ /* 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; } 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... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -983,7 +983,7 @@ skip_bitflip:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1067,7 +1067,7 @@ skip_bitflip:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1197,7 +1197,7 @@ skip_bitflip:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1331,7 +1331,7 @@ skip_arith:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1391,7 +1391,7 @@ skip_arith:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1479,7 +1479,7 @@ skip_arith:
/* Let's consult the effector map... */ /* 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1573,7 +1573,7 @@ skip_interest:
u32 last_len = 0; 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; } 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) { 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
@ -1708,7 +1708,7 @@ skip_user_extras:
u32 last_len = 0; 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; } 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) { 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; } if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }

View File

@ -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, /* Mark / unmark as redundant (edge-only). This is not used for restoring state,
but may be useful for post-processing datasets. */ 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; } if (likely(state == q->fs_redundant)) { return; }
char fn[PATH_MAX];
q->fs_redundant = state; q->fs_redundant = state;
if (likely(q->fs_redundant)) { 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) { if (state) {
s32 fd;
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; } 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);*/
}
} }
@ -805,6 +766,7 @@ void destroy_queue(afl_state_t *afl) {
for (i = 0; i < afl->queued_items; i++) { for (i = 0; i < afl->queued_items; i++) {
q = afl->queue_buf[i]; q = afl->queue_buf[i];
ck_free(q->testcase_buf);
ck_free(q->fname); ck_free(q->fname);
ck_free(q->trace_mini); ck_free(q->trace_mini);
if (q->skipdet_e) { if (q->skipdet_e) {
@ -833,7 +795,8 @@ void destroy_queue(afl_state_t *afl) {
previous contender, or if the contender has a more favorable speed x size previous contender, or if the contender has a more favorable speed x size
factor. */ 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; u32 i;
u64 fav_factor; u64 fav_factor;
@ -863,6 +826,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
} }
if (have_trace) {
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
winner, and how it compares to us. */ winner, and how it compares to us. */
for (i = 0; i < afl->fsrv.map_size; ++i) { for (i = 0; i < afl->fsrv.map_size; ++i) {
@ -906,7 +871,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
if (likely(fav_factor > top_rated_fav_factor)) { continue; } if (likely(fav_factor > top_rated_fav_factor)) { continue; }
/* Looks like we're going to win. Decrease ref count for the /* Looks like we're going to win. Decrease ref count for the
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */ previous winner, discard its afl->fsrv.trace_bits[] if necessary.
*/
if (!--afl->top_rated[i]->tc_ref) { if (!--afl->top_rated[i]->tc_ref) {
@ -924,7 +890,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
if (!q->trace_mini) { 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); q->trace_mini = (u8 *)ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
@ -938,6 +904,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
} }
}
/* The second part of the mechanism discussed above is a routine that /* The second part of the mechanism discussed above is a routine that
goes over afl->top_rated[] entries, and then sequentially grabs winners for goes over afl->top_rated[] entries, and then sequentially grabs winners for
previously-unseen bytes (temp_v) and marks them as favored, at least previously-unseen bytes (temp_v) and marks them as favored, at least
@ -1025,6 +993,186 @@ 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, (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) {
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. /* Calculate case desirability score to adjust the length of havoc fuzzing.
A helper function for fuzz_one(). Maybe some of these constants should A helper function for fuzz_one(). Maybe some of these constants should
go into config.h. */ go into config.h. */
@ -1330,7 +1478,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
// only realloc if necessary or useful // only realloc if necessary or useful
// (a custom trim can make the testcase larger) // (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; afl->q_testcase_cache_size += len - old_len;
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len); q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
@ -1364,7 +1512,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
if (likely(in != q->testcase_buf)) { if (likely(in != q->testcase_buf)) {
// only realloc if we save memory // 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); u8 *ptr = (u8 *)realloc(q->testcase_buf, len);

View File

@ -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 // note: from_queue seems to only be set during initialization
if (afl->afl_env.afl_no_ui || from_queue) { 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) { } else if (afl->debug) {
DEBUGF("instability detected during calibration\n"); DEBUGF("instability detected during calibration: %s\n", q->fname);
} }
@ -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_size += q->bitmap_size;
++afl->total_bitmap_entries; ++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 /* 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 parent. This is a non-critical problem, but something to warn the user
@ -682,12 +682,7 @@ abort_calibration:
afl->var_byte_count = count_bytes(afl, afl->var_bytes); afl->var_byte_count = count_bytes(afl, afl->var_bytes);
if (!q->var_behavior) { if (!q->var_behavior) { ++afl->queued_variable; }
mark_as_variable(afl, q);
++afl->queued_variable;
}
} }
@ -872,7 +867,14 @@ void sync_fuzzers(afl_state_t *afl) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); 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->syncing_party = sd_ent->d_name;
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault); afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
@ -1166,7 +1168,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); queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len);
memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size); memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size);
update_bitmap_score(afl, q); update_bitmap_score(afl, q, true);
} }

View File

@ -154,7 +154,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
flip_range(out_buf, pos, flip_block_size); 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)) { return 0; }
flip_range(out_buf, pos, flip_block_size); flip_range(out_buf, pos, flip_block_size);
@ -237,26 +237,26 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
if (!skip_eff_map) { 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; afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map;
} else { } else {
memset(skip_eff_map, 0, sizeof(u8) * len); memset(skip_eff_map, 0, sizeof(u8) * (len + 7) / 8);
} }
/* restore the starting point */ /* restore the starting point */
if (!done_inf_map) { 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; afl->queue_cur->skipdet_e->done_inf_map = done_inf_map;
} else { } else {
for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) { 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;
} }
@ -278,7 +278,13 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len); non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len);
// clean exec cksum // 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); prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
} }
@ -294,7 +300,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
afl->stage_cur_byte = afl->stage_cur; afl->stage_cur_byte = afl->stage_cur;
if (!inf_eff_map[afl->stage_cur_byte] || 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; continue;
if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; } if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; }
@ -311,7 +317,12 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
before_skip_inf = afl->queued_items; 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(non_eff_bytes);
return 0;
}
out_buf[afl->stage_cur_byte] = orig; out_buf[afl->stage_cur_byte] = orig;
@ -328,7 +339,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
if (afl->queued_items != before_skip_inf) { 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; afl->queue_cur->skipdet_e->quick_eff_bytes += 1;
if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; } if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; }
@ -338,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);
} }
@ -364,7 +375,7 @@ cleanup_skipdet:
while (i < len) { while (i < len) {
// assume DWORD size, from i - 3 -> i + 3 // 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; u32 fill_length = (i + 3 < len) ? 7 : len - i + 2;
memset(nearby_bytes + i - 3, 1, fill_length); memset(nearby_bytes + i - 3, 1, fill_length);
@ -378,7 +389,7 @@ cleanup_skipdet:
for (i = 0; i < len; i++) { 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);
} }

View File

@ -106,6 +106,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000; afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000;
afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL; afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL;
afl->q_testcase_max_cache_entries = 64 * 1024; afl->q_testcase_max_cache_entries = 64 * 1024;
afl->last_scored_idx = -1;
#ifdef HAVE_AFFINITY #ifdef HAVE_AFFINITY
afl->cpu_aff = -1; /* Selected CPU core */ afl->cpu_aff = -1; /* Selected CPU core */
@ -738,6 +739,21 @@ void afl_state_deinit(afl_state_t *afl) {
if (afl->pass_stats) { ck_free(afl->pass_stats); } if (afl->pass_stats) { ck_free(afl->pass_stats); }
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); } if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
if (afl->cmplog_binary) { ck_free(afl->cmplog_binary); } 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->queue_buf);
afl_free(afl->out_buf); afl_free(afl->out_buf);
@ -746,6 +762,8 @@ void afl_state_deinit(afl_state_t *afl) {
afl_free(afl->in_buf); afl_free(afl->in_buf);
afl_free(afl->in_scratch_buf); afl_free(afl->in_scratch_buf);
afl_free(afl->ex_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_bits);
ck_free(afl->virgin_tmout); ck_free(afl->virgin_tmout);
@ -757,6 +775,11 @@ void afl_state_deinit(afl_state_t *afl) {
ck_free(afl->first_trace); ck_free(afl->first_trace);
ck_free(afl->map_tmp_buf); 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); list_remove(&afl_states, afl);
} }

View File

@ -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) { 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; u64 current_ms = get_cur_time() - afl->start_time;
u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits);

View File

@ -1750,25 +1750,35 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->cycle_schedules) {
afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32));
}
if (afl->san_binary_length) {
if (afl->san_abstraction == UNIQUE_TRACE) {
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8)); 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)); 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_FORKSRV")) { afl->no_forkserver = 1; }
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; } if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
if (afl->afl_env.afl_autoresume) { if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; }
afl->autoresume = 1;
if (afl->in_place_resume) {
SAYF("AFL_AUTORESUME has no effect for '-i -'");
}
}
if (afl->afl_env.afl_hang_tmout) { if (afl->afl_env.afl_hang_tmout) {
@ -2326,8 +2336,8 @@ int main(int argc, char **argv_orig, char **envp) {
u8 ver_string[8]; u8 ver_string[8];
u64 *ver = (u64 *)ver_string; u64 *ver = (u64 *)ver_string;
u64 expect_ver = u64 expect_ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode +
afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); (sizeof(struct queue_entry) << 1);
if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) != if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) !=
sizeof(ver_string)) sizeof(ver_string))
@ -2605,7 +2615,7 @@ int main(int argc, char **argv_orig, char **envp) {
} else { } else {
WARNF("Unknown abstraction: %s, fallback to unique trace.\n", WARNF("Unknown abstraction: %s, fallback to simplified trace.\n",
san_abstraction); san_abstraction);
afl->san_abstraction = SIMPLIFY_TRACE; afl->san_abstraction = SIMPLIFY_TRACE;
@ -2843,7 +2853,7 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
u32 r = 8 + afl->fsrv.map_size * 4; u32 r = 8 + afl->fsrv.map_size * 4;
u32 q_len = o_end - o_start; 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; struct queue_entry *q;
for (u32 i = 0; i < afl->queued_items; i++) { for (u32 i = 0; i < afl->queued_items; i++) {
@ -2866,7 +2876,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->total_bitmap_size += q->bitmap_size; afl->total_bitmap_size += q->bitmap_size;
++afl->total_bitmap_entries; ++afl->total_bitmap_entries;
update_bitmap_score(afl, q); update_bitmap_score(afl, q, false);
if (q->was_fuzzed) { --afl->pending_not_fuzzed; } if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
@ -3236,15 +3246,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
// we must recalculate the scores of all queue entries // we must recalculate the scores of all queue entries
for (u32 i = 0; i < afl->queued_items; i++) { recalculate_all_scores(afl);
if (likely(!afl->queue_buf[i]->disabled)) {
update_bitmap_score(afl, afl->queue_buf[i]);
}
}
} }
@ -3546,7 +3548,8 @@ stop_fuzzing:
u8 ver_string[8]; u8 ver_string[8];
u32 w = 0; u32 w = 0;
u64 *ver = (u64 *)ver_string; 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, ver_string, sizeof(ver_string), "ver_string");
ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
@ -3559,7 +3562,7 @@ stop_fuzzing:
u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
u32 q_len = o_end - o_start; 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; struct queue_entry *q;
afl->pending_not_fuzzed = afl->queued_items; afl->pending_not_fuzzed = afl->queued_items;
@ -3626,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); } if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.target_path);
ck_free(afl->fsrv.out_file); ck_free(afl->fsrv.out_file);

View File

@ -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)afl;
(void)q; (void)q;
(void)x;
} }

View File

@ -106,11 +106,15 @@ __attribute__((weak)) void __asan_unpoison_memory_region(
__attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size); __attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size);
// Notify AFL about persistent mode. // Notify AFL about persistent mode.
static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; __attribute__((section(".rodata"), used,
retain)) static const char AFL_PERSISTENT[] =
"##SIG_AFL_PERSISTENT##";
int __afl_persistent_loop(unsigned int); int __afl_persistent_loop(unsigned int);
// Notify AFL about deferred forkserver. // Notify AFL about deferred forkserver.
static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; __attribute__((section(".rodata"), used,
retain)) static const char AFL_DEFER_FORKSVR[] =
"##SIG_AFL_DEFER_FORKSRV##";
void __afl_manual_init(); void __afl_manual_init();
// Use this optionally defined function to output sanitizer messages even if // Use this optionally defined function to output sanitizer messages even if
@ -350,11 +354,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
// Do any other expensive one-time initialization here. // 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; int N = INT_MAX;
if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) { if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {

View File

@ -11,12 +11,12 @@
#include <dlfcn.h> #include <dlfcn.h>
#ifdef __ANDROID__ #ifdef __ANDROID__
#include "../include/android-ashmem.h" #include "../../include/android-ashmem.h"
#endif #endif
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#include "../config.h" #include "../../config.h"
#include <QBDI.h> #include <QBDI.h>
@ -81,7 +81,7 @@ static void afl_forkserver() {
while (1) { while (1) {
int status; int status;
u32 was_killed; unsigned int was_killed;
// wait for afl-fuzz // wait for afl-fuzz
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);