Compare commits

...

59 Commits

Author SHA1 Message Date
c340a022e2 Merge pull request #2401 from AFLplusplus/dev
v4.32c release
2025-04-26 15:36:45 +02:00
06219b4d56 v4.32c 2025-04-26 15:35:47 +02:00
c5b8f4250e code format 2025-04-26 15:30:56 +02:00
779cb5d942 Merge pull request #2400 from AFLplusplus/dev
push to stable
2025-04-26 15:30:18 +02:00
fb1a41f5af fix 2025-04-26 13:24:21 +02:00
8352f0a89f fix LLVM 20 pass pipeline insertion 2025-04-26 13:20:51 +02:00
9935190c7b drop llvm 13 AFL++ plugin support 2025-04-25 18:37:19 +02:00
e3ee26262f fix AFL_OLD_FORKSERVER 2025-04-25 13:42:19 +02:00
737c13b460 Merge pull request #2386 from 5angjun/dev
Add someone else to the "list of contributors" :)
2025-04-25 10:03:37 +02:00
9836598d65 Merge pull request #2398 from kcwu/fix-minor
Minor fixes
2025-04-25 10:03:23 +02:00
63509fb696 fix afl-cmin message output 2025-04-25 11:51:34 +08:00
d1c44e12a8 remove dead comment 2025-04-25 11:51:20 +08:00
f78ed6eabc remove redundent code 2025-04-25 11:51:08 +08:00
64c942d0c9 fix printf format 2025-04-25 11:50:50 +08:00
50e343a0d0 Merge branch 'dev' into dev 2025-04-25 11:23:33 +09:00
55719ab23b Resolve merge conflict in README.md 2025-04-25 11:19:52 +09:00
d12c5edd59 Merge pull request #2395 from ryberger-nvidia/fix-infinite-loop
fix infinite loop when custom mutator rejects smallest_favored
2025-04-24 16:04:41 +02:00
1b82d6b904 fix for nit in afl-tmin 2025-04-24 14:42:32 +02:00
61201fbbb8 fix infinite loop when custom mutator rejects smallest_favored
When running with custom mutators, afl-fuzz delegates the responsibility of queuing to` afl_custom_queue_get`
implemented by the mutator. If any mutator cannot process the input, then it is rejected. After an input is rejected
then a new suitable item to queue must be found. Before this PR, that would be `smallest_favored`. However,
if `smallest_favored` were rejected, it would not be cleared from its position as  `smallest_favored` meaning it
would be attempted to be queued again catching afl-fuzz in an infinite loop.

To fix it, we simply return that we skipped the entry, along with using a `goto abandon_entry` to clean the entry up so that
the fuzzer never considers the input again
2025-04-23 14:47:55 -07:00
b9458e72e7 nit 2025-04-23 16:42:49 +02:00
5045f9e615 code format 2025-04-21 11:45:33 +02:00
6cd8a0168f Merge pull request #2391 from kcwu/fix-__AFL_COVERAGE
fix __AFL_COVERAGE: multiple definition of `__afl_selective_coverage`
2025-04-21 11:45:05 +02:00
448c6c212d fix __AFL_COVERAGE: multiple definition of __afl_selective_coverage
fix #2390
2025-04-21 09:02:23 +00:00
05f4762894 nits 2025-04-21 10:59:59 +02:00
0a06e36788 Merge pull request #2336 from gitToki/stable
Enhancement: Custom Python trimming support to afl-tmin
2025-04-19 15:50:42 +02:00
9b1f80c277 Merge pull request #2388 from kcwu/fix-changelog
fix 4.31c change log
2025-04-19 15:36:42 +02:00
787a332a73 fix 4.31c change log
the splicing auto enable is removed by b2a01936c3
2025-04-19 12:13:36 +00:00
7d85047fd9 update bitmap api 2025-04-17 15:28:31 +02:00
fa8dc2028f Merge branch 'AFLplusplus:stable' into stable 2025-04-17 15:20:31 +02:00
619aa70414 Add someone else to the "list of contributors" :) 2025-04-17 16:28:35 +09:00
247e8241b4 Merge pull request #2360 from AFLplusplus/dev
push to stable
2025-04-16 18:14:35 +02:00
0bb64e4bc9 Merge pull request #2384 from fanquake/ubuntu_20_04_removed
Ubuntu 20.04 removed by GitHub
2025-04-16 17:52:30 +02:00
7b84ec97e2 Merge pull request #2383 from fanquake/fix_lld_version
build: improve lld version parsing
2025-04-16 15:18:09 +02:00
20a6cdabad ci: drop usage of ubuntu:20.04
Support for this has been removed by GitHub:
https://github.com/actions/runner-images/issues/11101.
2025-04-16 14:03:36 +01:00
0d286c9e19 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
```
2025-04-16 13:37:15 +01:00
db94ec9cad Merge pull request #2382 from kcwu/fix-performance-unit
fix build for "make PERFORMANCE=1 unit"
2025-04-16 10:14:43 +02:00
05dfb70787 fix build for "make PERFORMANCE=1 unit" 2025-04-16 00:48:30 +00:00
7f2becba72 build fix for asan+performance 2025-04-14 13:57:45 +02:00
13b27bb59e Merge pull request #2375 from kcwu/format-cache
code-format cache
2025-04-14 10:11:50 +02:00
ecdbdc3164 Merge pull request #2377 from kcwu/fix-custom-format
fix in_define in .custom-format.py
2025-04-14 10:10:38 +02:00
788e70a01a Merge pull request #2379 from r3sting/patch-1
Fix linker error
2025-04-14 10:09:43 +02:00
938ed60ea9 Merge pull request #2380 from kcwu/fix-memory-leak
Fix memory leak
2025-04-14 10:09:03 +02:00
5b9d2cc38b code-format cache
This change reduces "make code-format" from 3 minutes to 3 seconds if
large files are not changed.
2025-04-13 08:26:18 +00:00
e305bc15d3 fix memory leaks 2025-04-13 06:46:46 +00:00
0b12c7e0cc Fix linker error 2025-04-12 16:20:33 -06:00
4bd492f212 fix memory leak in check_main_node_exists 2025-04-12 16:56:14 +00:00
be8393f201 fix in_define in .custom-format.py
avoid the extra \ before #define line
2025-04-12 15:56:36 +00:00
aec90c7227 Merge pull request #2376 from kcwu/minor-changes
Minor changes
2025-04-12 16:01:34 +02:00
1960352310 add custom mutator support for afl tmin 2025-04-12 14:55:30 +02:00
03169b2b67 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.
2025-04-12 11:16:11 +00:00
dee51213a7 update build dependency rule in GNUmakefile 2025-04-12 11:16:11 +00:00
1d2de1cb6d remove dead code in comment 2025-04-12 11:15:25 +00:00
5ed187b517 fix for cycle_schedule change 2025-04-12 12:57:37 +02:00
757184e611 adjustment 2025-04-06 01:37:15 +02:00
27b18e6267 refactor/ Use functions from other files instead of creating new ones 2025-04-05 21:08:08 +02:00
f3b15d6340 fmt 2025-04-01 17:59:59 +02:00
0134a23046 impl normal custom mutators 2025-04-01 17:55:43 +02:00
542233e1ce custom python mutators in afl-tmin 2025-03-28 00:36:12 +01:00
8e4823e7ed add python flag to gnumakefile 2025-03-27 22:20:13 +01:00
29 changed files with 505 additions and 91 deletions

View File

@ -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(":")
@ -86,9 +91,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 +132,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
@ -136,6 +140,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] <filename>")
@ -151,7 +187,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)

View File

@ -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

3
.gitignore vendored
View File

@ -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
argv_fuzz_persistent_demo

View File

@ -289,7 +289,7 @@ ifneq "$(findstring OpenBSD, $(SYS))" ""
override LDFLAGS += -lpthread -lm
endif
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h include/afl-fuzz.h include/hash.h include/sharedmem.h include/forkserver.h include/common.h include/list.h
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
PYTHON_OK=1
@ -472,32 +472,32 @@ endif
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
src/afl-performance.o: $(COMM_HDR) src/afl-performance.c
$(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/envs.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
src/afl-forkserver.o: $(COMM_HDR) src/afl-forkserver.c
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
src/afl-sharedmem.o: $(COMM_HDR) src/afl-sharedmem.c include/android-ashmem.h include/cmplog.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o include/cmplog.h include/envs.h | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
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 $@"; }
endif
afl-tmin: src/afl-tmin.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-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o -o $@ $(PYFLAGS) $(LDFLAGS)
ifdef IS_IOS
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
endif
@ -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 $@"; }
@ -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

View File

@ -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

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
Release version: [4.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.32c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.32a
GitHub version: 4.32c
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@ -16,7 +16,6 @@ AFL++ is maintained by:
* Andrea Fioraldi <andreafioraldi@gmail.com>
* Heiko "hexcoder-" Eissfeldt <heiko.eissfeldt@hexco.de>
* frida_mode is maintained by @Worksbutnottested
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
Originally developed by Michal "lcamtuf" Zalewski.
@ -230,7 +229,8 @@ Thank you! (For people sending pull requests - please add yourself to this list
Ruben ten Hove Joey Jiao
fuzzah @intrigus-lgtm
Yaakov Saxon Sergej Schumilo
Ziqiao Kong
Ziqiao Kong Ryan Berger
Sangjun Park
```
</details>

View File

@ -331,7 +331,7 @@ BEGIN {
}
if (0 == system ( "grep -aq AFL_DUMP_MAP_SIZE " target_bin )) {
echo "[!] Trying to obtain the map size of the target ..."
print "[!] Trying to obtain the map size of the target ..."
get_map_size = "AFL_DUMP_MAP_SIZE=1 " target_bin
get_map_size | getline mapsize
close(get_map_size)

View File

@ -3,15 +3,22 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.32a (dev)
### Version ++4.32c (release)
- 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!
- some more nits and small memory saves thanks to @kcwu
- many 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
- fix for afl_custom_queue_get
- various small nits
- afl-cc:
- fix pass support for LLVM 20 (passes were run too early)
- dropped plugin support for LLVM 13
- fix AFL_OLD_FORKSERVER
- various minor fixes
- frida_mode:
- fixes for new MacOS + M4 hardware
@ -22,7 +29,7 @@
- afl-fuzz:
- splicing phase is now DISABLED by default because research showed
it is counterproductive. New command line parameter `-u` to enable
it. Splicing is auto-enabled if two cycles without finds happen.
it.
- Python 3.13+ support
- loose file and shared memory permissions on Android and iPhone
- afl-cc:

View File

@ -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);
}

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.32a"
#define VERSION "++4.32c"
/******************************************************
* *

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,
size_t len, XXH_alignment align) {
\
#define XXH_PROCESS1 \
do { \
\

View File

@ -226,20 +226,28 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM,
OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(ModuleSanitizerCoverageAFL());
});
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(ModuleSanitizerCoverageAFL());
});
#endif
}};
}

View File

@ -891,10 +891,10 @@ static void __afl_start_forkserver(void) {
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
if (!__afl_old_forkserver) {
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
if (!__afl_old_forkserver) {
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {

View File

@ -121,15 +121,16 @@ extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
#endif
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(AFLCoverage());

View File

@ -130,15 +130,16 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
#endif
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(CompareTransform());

View File

@ -190,15 +190,16 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
#endif
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(SplitComparesTransform());

View File

@ -138,15 +138,17 @@ llvmGetPassPluginInfo() {
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
#if LLVM_VERSION_MAJOR >= 20
PB.registerPipelineStartEPCallback(
#else
PB.registerOptimizerEarlyEPCallback(
#endif
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
[](ModulePassManager &MPM, OptimizationLevel OL
#if LLVM_VERSION_MAJOR >= 20
,
ThinOrFullLTOPhase Phase
#endif
) {
MPM.addPass(SplitSwitchesTransform());

View File

@ -40,7 +40,7 @@ ALPINE_ROOT=<your-alpine-sysroot-directory>
FUZZ=<your-path-to-the-code>
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
```

View File

@ -253,7 +253,11 @@ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
#if LLVM_MAJOR < 16
#if LLVM_MAJOR < 15
insert_param(aflcc, "-fno-legacy-pass-manager");
#else
insert_param(aflcc, "-fexperimental-new-pass-manager");
#endif
#endif
insert_object(aflcc, pass, "-fpass-plugin=%s", 0);
#else
@ -1534,7 +1538,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
if (aflcc->plusplus_mode) {
insert_param(aflcc,
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
"__attribute__ ((weak)) = 1;"
"extern \"C\" void __afl_coverage_discard();"
"extern \"C\" void __afl_coverage_skip();"
"extern \"C\" void __afl_coverage_on();"
@ -1543,7 +1548,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
} else {
insert_param(aflcc,
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
"__attribute__ ((weak)) = 1;"
"void __afl_coverage_discard();"
"void __afl_coverage_skip();"
"void __afl_coverage_on();"
@ -2161,7 +2167,11 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) {
/* Since LLVM_MAJOR >= 13 we use new pass manager */
#if LLVM_MAJOR < 16
#if LLVM_MAJOR < 15
insert_param(aflcc, "-fno-legacy-pass-manager");
#else
insert_param(aflcc, "-fexperimental-new-pass-manager");
#endif
#endif
insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0);
@ -3589,6 +3599,64 @@ int main(int argc, char **argv, char **envp) {
}
// We only support plugins with LLVM 14 onwards
#if LLVM_MAJOR < 14
if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE &&
aflcc->compiler_mode != GCC_PLUGIN) {
aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE;
aflcc->compiler_mode = LLVM;
}
if (aflcc->compiler_mode == LLVM) {
if (aflcc->cmplog_mode) {
WARNF("CMPLOG support requires LLVM 14+");
aflcc->cmplog_mode = 0;
}
if (getenv("AFL_LLVM_DICT2FILE")) {
WARNF("DICT2FILE support requires LLVM14+");
unsetenv("AFL_LLVM_DICT2FILE");
}
if (getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_ALL")) {
WARNF("AFL_LLVM_LAF support requires LLVM14+");
unsetenv("AFL_LLVM_LAF_SPLIT_SWITCHES");
unsetenv("AFL_LLVM_LAF_SPLIT_COMPARES");
unsetenv("AFL_LLVM_LAF_SPLIT_FLOATS");
unsetenv("AFL_LLVM_LAF_TRANSFORM_COMPARES");
unsetenv("AFL_LLVM_LAF_ALL");
}
if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
getenv("AFL_LLVM_INJECTIONS_SQL") ||
getenv("AFL_LLVM_INJECTIONS_LDAP") ||
getenv("AFL_LLVM_INJECTIONS_XSS")) {
WARNF("AFL_LLVM_INJECTIONS support requires LLVM14+");
unsetenv("AFL_LLVM_INJECTIONS_ALL");
unsetenv("AFL_LLVM_INJECTIONS_SQL");
unsetenv("AFL_LLVM_INJECTIONS_LDAP");
unsetenv("AFL_LLVM_INJECTIONS_XSS");
}
}
#endif
mode_notification(aflcc);
if (aflcc->debug) debugf_args(argc, argv);

View File

@ -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 { \
\

View File

@ -686,7 +686,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
#else
queue_fn = alloc_printf(
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
"%s/queue/id_%06u%s%s", afl->out_dir, afl->queued_items,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");

View File

@ -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;
}

View File

@ -356,7 +356,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (el->afl_custom_queue_get &&
!el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
return 1;
/* Abandon the entry and return that we skipped it.
If we don't do this then when the entry is smallest_favored then
we get caught in an infinite loop calling afl_custom_queue_get
on smallest_favored */
ret_val = 1;
goto abandon_entry;
}

View File

@ -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) {

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
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);
}
@ -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);

View File

@ -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);

View File

@ -1555,13 +1555,6 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
// silently disable deterministic mutation if custom mutators are used
if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
afl->skip_deterministic = 1;
}
if (afl->fixed_seed) {
OKF("Running with fixed seed: %u", (u32)afl->init_seed);

View File

@ -1261,8 +1261,6 @@ int main(int argc, char **argv_orig, char **envp) {
break;
/* FIXME: We want to use -P for consistency, but it is already unused for
* undocumenetd feature "Another afl-cmin specific feature." */
case 'A': /* CoreSight mode */
#if !defined(__aarch64__) || !defined(__linux__)

View File

@ -37,6 +37,8 @@
#include "forkserver.h"
#include "sharedmem.h"
#include "common.h"
#include "afl-fuzz.h"
#include "list.h"
#include <stdio.h>
#include <unistd.h>
@ -48,6 +50,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <libgen.h>
#include <sys/wait.h>
#include <sys/time.h>
@ -57,8 +60,30 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#ifdef USE_PYTHON
#include <Python.h>
#endif
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
extern void destroy_custom_mutators(afl_state_t *);
void list_init(list_t *list) {
if (list) {
list->element_prealloc_count = 0;
memset(list->element_prealloc_buf, 0, sizeof(list->element_prealloc_buf));
}
}
void setup_custom_mutators(afl_state_t *);
struct custom_mutator *load_custom_mutator(afl_state_t *, const char *);
#ifdef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
#endif
static afl_state_t *afl; /* State for custom mutators */
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
static u8 *in_file, /* Minimizer input test case */
*out_file, *output_file; /* Minimizer output file */
@ -135,6 +160,52 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
}
/* dummy functions */
u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
(void)afl;
(void)mem;
return a + b;
}
void show_stats(afl_state_t *afl) {
(void)afl;
}
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
bool add_to_queue) {
(void)afl;
(void)q;
(void)add_to_queue;
}
fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
u32 i) {
(void)afl;
(void)fsrv;
(void)i;
return 0;
}
#ifndef USE_PYTHON
struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module) {
(void)afl;
(void)module;
FATAL("Python support not available in this build");
return NULL;
}
#endif
/* Apply mask to classified bitmap (if set). */
static void apply_mask(u32 *mem, u32 *mask) {
@ -153,7 +224,7 @@ static void apply_mask(u32 *mem, u32 *mask) {
}
static void classify_counts(afl_forkserver_t *fsrv) {
void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
u32 i = map_size;
@ -209,6 +280,13 @@ static void at_exit_handler(void) {
afl_fsrv_killall();
if (remove_out_file) unlink(out_file);
if (afl) {
destroy_custom_mutators(afl);
ck_free(afl);
}
}
/* Read initial file. */
@ -259,14 +337,72 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
}
/* Helper function to handle custom mutators for testcase writing */
static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
static u8 buf[MAX_FILE];
u32 sent = 0;
if (afl && afl->custom_mutators_count) {
ssize_t new_size = len;
u8 *new_mem = mem;
u8 *new_buf = NULL;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_post_process) {
new_size =
el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
if (!new_buf || new_size <= 0) {
return;
} else {
new_mem = new_buf;
len = new_size;
}
}
});
if (new_mem != mem && new_mem != NULL) {
mem = buf;
memcpy(mem, new_mem, new_size);
}
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz_send) {
el->afl_custom_fuzz_send(el->data, mem, len);
sent = 1;
}
});
}
if (!sent) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
}
/* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */
static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
u8 first_run) {
afl_fsrv_write_to_testcase(fsrv, mem, len);
pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
@ -357,14 +493,132 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
static void minimize(afl_forkserver_t *fsrv) {
static u32 alpha_map[256];
u8 *tmp_buf = ck_alloc_nozero(in_len);
u32 orig_len = in_len, stage_o_len;
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
u8 *tmp_buf = ck_alloc_nozero(in_len);
u32 orig_len = in_len, stage_o_len;
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0;
u8 changed_any, prev_del;
#ifdef USE_PYTHON
// Try to load python module
char *py_module = getenv("AFL_PYTHON_MODULE");
if (py_module) {
// We cannot use Python custom mutators in tmin
if (debug) WARNF("Python custom mutator support not available in afl-tmin");
}
#endif
// Custom mutator trimming
if (afl && afl->custom_mutators_count) {
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_init_trim && el->afl_custom_trim &&
el->afl_custom_post_trim) {
ACTF("Performing custom trim with %s...", el->name);
// Initialize the trimmer
s32 initial_steps = el->afl_custom_init_trim(el->data, in_data, in_len);
if (initial_steps <= 0) {
WARNF("Custom trimmer %s returned %d, skipping", el->name,
initial_steps);
continue;
}
ACTF("Custom trimmer initialized, %d steps planned", initial_steps);
u32 trim_rounds = 0;
u32 trimmed_successfully = 0;
// Trim loop
s32 cur_step = 0;
while (cur_step < initial_steps) {
u8 *trimmed_buf = NULL;
size_t trimmed_size;
u8 *retbuf = NULL;
trimmed_size = el->afl_custom_trim(el->data, &retbuf);
// If trimmed_size equals or exceeds original size, skip
if (trimmed_size >= in_len) {
SAYF("[Custom trim] Round %u: no improvements over %u bytes.\n",
trim_rounds, in_len);
el->afl_custom_post_trim(el->data, 0);
cur_step++;
trim_rounds++;
continue;
}
trimmed_buf = retbuf;
// Test if the trimmed case still works
if (!tmin_run_target(fsrv, trimmed_buf, trimmed_size, 0)) {
SAYF(
"[Custom trim] But the testcase no longer reproduces - "
"skipping this reduction.\n");
el->afl_custom_post_trim(el->data, 0);
if (trimmed_buf != in_data) { ck_free(trimmed_buf); }
} else {
// Accept the reduction
u8 *old_in_data = in_data;
in_data = trimmed_buf;
in_len = trimmed_size;
trimmed_successfully = 1;
el->afl_custom_post_trim(el->data, 1);
SAYF("[Custom trim] Successful reduction to %u bytes\n", in_len);
if (old_in_data != in_data && old_in_data != trimmed_buf) {
ck_free(old_in_data);
}
}
cur_step++;
trim_rounds++;
}
ACTF("Custom trimming with %s complete after %u rounds, reduced: %s",
el->name, trim_rounds, trimmed_successfully ? "yes" : "no");
if (trimmed_successfully) {
if (tmp_buf) { ck_free(tmp_buf); }
return; // Skip standard minimization if successful
}
}
});
}
// Skip built-in minimization if in_len is too small
if (in_len <= 1) {
if (tmp_buf) { ck_free(tmp_buf); }
return;
}
/***********************
* BLOCK NORMALIZATION *
***********************/
@ -747,7 +1001,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
/* Setup signal handlers, duh. */
static void setup_signal_handlers(void) {
void setup_signal_handlers(void) {
struct sigaction sa;
@ -1243,6 +1497,29 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
// Initialize AFL state for custom mutators
afl = calloc(1, sizeof(afl_state_t));
if (afl) {
list_init(&afl->custom_mutator_list);
afl->custom_mutators_count = 0;
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
afl->afl_env.afl_custom_mutator_library =
getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
afl->shm = shm;
afl->out_dir = dirname(in_file);
memcpy(&afl->fsrv, fsrv, sizeof(afl_forkserver_t));
setup_custom_mutators(afl);
}
#ifdef __linux__
if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
#else