aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-01-20 19:12:52 +0100
committerGitHub <noreply@github.com>2021-01-20 19:12:52 +0100
commit068bef5eab942df0a133c92522f2ab81b28ac636 (patch)
tree4689cb46e0d543af889609e260b1ff03455a2701
parent271116f8705e08d1b4f924cda6c6cae1b0b5de2b (diff)
parentb9e855b7b5ef3d7f367b32ee03459a9f5b21360f (diff)
downloadafl++-068bef5eab942df0a133c92522f2ab81b28ac636.tar.gz
Merge pull request #691 from AFLplusplus/dev
push to stable
-rw-r--r--Android.bp176
l---------Android.mk1
-rw-r--r--README.md15
-rwxr-xr-xafl-cmin1
-rwxr-xr-xafl-system-config14
-rwxr-xr-xafl-wine-trace4
-rw-r--r--custom_mutators/Android.bp115
-rw-r--r--custom_mutators/honggfuzz/mangle.c2
-rw-r--r--custom_mutators/libfuzzer/FuzzerDataFlowTrace.cpp10
-rw-r--r--custom_mutators/libfuzzer/FuzzerDefs.h2
-rw-r--r--custom_mutators/libfuzzer/FuzzerDictionary.h4
-rw-r--r--custom_mutators/libfuzzer/FuzzerRandom.h2
-rw-r--r--custom_mutators/libfuzzer/FuzzerTracePC.h8
-rw-r--r--custom_mutators/libprotobuf-mutator-example/Android.bp32
-rw-r--r--custom_mutators/libprotobuf-mutator-example/README.md1
-rw-r--r--custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.cc118
-rw-r--r--custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.h5
-rw-r--r--custom_mutators/libprotobuf-mutator-example/test.proto7
-rw-r--r--custom_mutators/libprotobuf-mutator-example/vuln.c17
-rw-r--r--docs/Changelog.md11
-rw-r--r--docs/env_variables.md4
-rw-r--r--docs/power_schedules.md4
-rw-r--r--docs/status_screen.md7
-rw-r--r--include/afl-fuzz.h16
-rw-r--r--include/android-ashmem.h113
-rw-r--r--include/common.h5
-rw-r--r--include/config.h50
-rw-r--r--include/debug.h6
-rw-r--r--include/envs.h1
-rw-r--r--include/forkserver.h2
-rw-r--r--include/types.h2
-rw-r--r--instrumentation/LLVMInsTrim.so.cc14
-rw-r--r--instrumentation/MarkNodes.cc2
-rw-r--r--instrumentation/README.instrument_list.md53
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc11
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc10
-rw-r--r--instrumentation/afl-compiler-rt.o.c189
-rw-r--r--instrumentation/afl-gcc-pass.so.cc11
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc6
-rw-r--r--instrumentation/afl-llvm-lto-instrumentation.so.cc35
-rw-r--r--instrumentation/afl-llvm-pass.so.cc12
-rw-r--r--instrumentation/cmplog-instructions-pass.cc89
-rw-r--r--instrumentation/compare-transform-pass.so.cc29
-rw-r--r--instrumentation/split-compares-pass.so.cc10
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--src/afl-analyze.c7
-rw-r--r--src/afl-cc.c148
-rw-r--r--src/afl-common.c58
-rw-r--r--src/afl-forkserver.c79
-rw-r--r--src/afl-fuzz-bitmap.c1
-rw-r--r--src/afl-fuzz-extras.c6
-rw-r--r--src/afl-fuzz-mutators.c33
-rw-r--r--src/afl-fuzz-one.c24
-rw-r--r--src/afl-fuzz-queue.c20
-rw-r--r--src/afl-fuzz-redqueen.c58
-rw-r--r--src/afl-fuzz-run.c35
-rw-r--r--src/afl-fuzz-state.c11
-rw-r--r--src/afl-fuzz-stats.c18
-rw-r--r--src/afl-fuzz.c59
-rw-r--r--src/afl-gotcpu.c3
-rw-r--r--src/afl-ld-lto.c7
-rw-r--r--src/afl-showmap.c31
-rw-r--r--src/afl-tmin.c12
-rwxr-xr-xtest/test-basic.sh10
-rw-r--r--unicorn_mode/UNICORNAFL_VERSION2
-rwxr-xr-xunicorn_mode/build_unicorn_support.sh9
m---------unicorn_mode/unicornafl0
-rw-r--r--utils/afl_frida/afl-frida.c201
-rw-r--r--utils/afl_frida/android/README.md1
-rw-r--r--utils/afl_frida/android/frida-gum-example.c130
-rw-r--r--utils/afl_network_proxy/afl-network-server.c4
-rw-r--r--utils/aflpp_driver/aflpp_driver.c65
-rw-r--r--utils/defork/defork.c2
-rw-r--r--utils/libdislocator/README.md2
-rw-r--r--utils/libdislocator/libdislocator.so.c8
-rw-r--r--utils/libtokencap/README.md7
-rw-r--r--utils/persistent_mode/Makefile8
-rw-r--r--utils/qemu_persistent_hook/test.c2
78 files changed, 1601 insertions, 688 deletions
diff --git a/Android.bp b/Android.bp
index 2c2114b2..5d6f0433 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,16 @@
cc_defaults {
name: "afl-defaults",
+ sanitize: {
+ never: true,
+ },
+
+ local_include_dirs: [
+ "include",
+ "instrumentation",
+ ],
cflags: [
+ "-flto=full",
"-funroll-loops",
"-Wno-pointer-sign",
"-Wno-pointer-arith",
@@ -10,16 +19,22 @@ cc_defaults {
"-Wno-unused-function",
"-Wno-format",
"-Wno-user-defined-warnings",
- "-DUSE_TRACE_PC=1",
+ "-DAFL_LLVM_USE_TRACE_PC=1",
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
"-D__USE_GNU",
+ "-D__aarch64__",
+ "-DDEBUG_BUILD",
+ "-U_FORTIFY_SOURCE",
+ "-ggdb3",
+ "-g",
+ "-O0",
+ "-fno-omit-frame-pointer",
],
}
cc_binary {
name: "afl-fuzz",
- static_executable: true,
host_supported: true,
defaults: [
@@ -27,7 +42,11 @@ cc_binary {
],
srcs: [
- "afl-fuzz.c",
+ "src/afl-fuzz*.c",
+ "src/afl-common.c",
+ "src/afl-sharedmem.c",
+ "src/afl-forkserver.c",
+ "src/afl-performance.c",
],
}
@@ -41,7 +60,10 @@ cc_binary {
],
srcs: [
- "afl-showmap.c",
+ "src/afl-showmap.c",
+ "src/afl-common.c",
+ "src/afl-sharedmem.c",
+ "src/afl-forkserver.c",
],
}
@@ -55,7 +77,11 @@ cc_binary {
],
srcs: [
- "afl-tmin.c",
+ "src/afl-tmin.c",
+ "src/afl-common.c",
+ "src/afl-sharedmem.c",
+ "src/afl-forkserver.c",
+ "src/afl-performance.c",
],
}
@@ -69,7 +95,10 @@ cc_binary {
],
srcs: [
- "afl-analyze.c",
+ "src/afl-analyze.c",
+ "src/afl-common.c",
+ "src/afl-sharedmem.c",
+ "src/afl-performance.c",
],
}
@@ -83,12 +112,13 @@ cc_binary {
],
srcs: [
- "afl-gotcpu.c",
+ "src/afl-gotcpu.c",
+ "src/afl-common.c",
],
}
cc_binary_host {
- name: "afl-clang-fast",
+ name: "afl-cc",
static_executable: true,
defaults: [
@@ -98,44 +128,144 @@ cc_binary_host {
cflags: [
"-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
+ "-DAFL_CLANG_FLTO=\"-flto=full\"",
+ "-DUSE_BINDIR=1",
+ "-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
+ "-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
+ "-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
+ "-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
+ "-DLLVM_LTO=1",
+ "-DLLVM_MAJOR=11",
+ "-DLLVM_MINOR=2",
],
srcs: [
"src/afl-cc.c",
+ "src/afl-common.c",
+ ],
+
+ symlinks: [
+ "afl-clang-fast",
+ "afl-clang-fast++",
],
}
-cc_binary_host {
- name: "afl-clang-fast++",
- static_executable: true,
+cc_library_static {
+ name: "afl-llvm-rt",
+ compile_multilib: "both",
+ vendor_available: true,
+ host_supported: true,
+ recovery_available: true,
+ sdk_version: "9",
- defaults: [
- "afl-defaults",
+ apex_available: [
+ "com.android.adbd",
+ "com.android.appsearch",
+ "com.android.art",
+ "com.android.bluetooth.updatable",
+ "com.android.cellbroadcast",
+ "com.android.conscrypt",
+ "com.android.extservices",
+ "com.android.cronet",
+ "com.android.neuralnetworks",
+ "com.android.media",
+ "com.android.media.swcodec",
+ "com.android.mediaprovider",
+ "com.android.permission",
+ "com.android.runtime",
+ "com.android.resolv",
+ "com.android.tethering",
+ "com.android.wifi",
+ "com.android.sdkext",
+ "com.android.os.statsd",
+ "//any",
],
- cflags: [
- "-D__ANDROID__",
- "-DAFL_PATH=\"out/host/linux-x86/lib64\"",
+ defaults: [
+ "afl-defaults",
],
srcs: [
- "src/afl-cc.c",
+ "instrumentation/afl-compiler-rt.o.c",
],
}
-cc_library_static {
- name: "afl-llvm-rt",
- compile_multilib: "both",
+cc_library_headers {
+ name: "libafl_headers",
vendor_available: true,
host_supported: true,
- recovery_available: true,
- sdk_version: "9",
+
+ export_include_dirs: [
+ "include",
+ ],
+}
+
+cc_prebuilt_library_static {
+ name: "libfrida-gum",
+ compile_multilib: "64",
+ strip: {
+ none: true,
+ },
+
+ srcs: [
+ "utils/afl_frida/android/libfrida-gum.a",
+ ],
+
+ export_include_dirs: [
+ "utils/afl_frida/android",
+ ],
+}
+
+cc_library_shared {
+ name: "libtestinstr",
+
+ srcs: [
+ "utils/afl_frida/libtestinstr.c",
+ ],
+
+ cflags: [
+ "-O0",
+ "-fPIC",
+ ],
+}
+
+cc_binary {
+ name: "afl-frida",
+ compile_multilib: "64",
defaults: [
"afl-defaults",
],
+ cflags: [
+ "-g",
+ "-O0",
+ "-Wno-format",
+ "-Wno-pointer-sign",
+ "-fpermissive",
+ "-fPIC",
+ ],
+
+ static_libs: [
+ "afl-llvm-rt",
+ "libfrida-gum",
+ ],
+
+ shared_libs: [
+ "libdl",
+ "liblog",
+ ],
+
srcs: [
- "instrumentation/afl-llvm-rt.o.c",
+ "utils/afl_frida/afl-frida.c",
+ ],
+
+ local_include_dirs: [
+ "utils/afl_frida",
+ "utils/afl_frida/android",
],
}
+
+subdirs = [
+ "custom_mutators",
+]
diff --git a/Android.mk b/Android.mk
deleted file mode 120000
index 33ceb8f0..00000000
--- a/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-Makefile \ No newline at end of file
diff --git a/README.md b/README.md
index bea673f9..348577df 100644
--- a/README.md
+++ b/README.md
@@ -505,10 +505,6 @@ more useful.
If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
seriously :-)
-Pro tip: load the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM)
-before the start of afl-fuzz as this improves performance by a x2 speed increase
-(less if you use a persistent mode harness)!
-
#### a) Running afl-fuzz
Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
@@ -591,13 +587,17 @@ For every secondary fuzzer there should be a variation, e.g.:
All other secondaries should be used like this:
* A third to a half with the MOpt mutator enabled: `-L 0`
* run with a different power schedule, available are:
- `explore (default), fast, coe, lin, quad, exploit, mmopt, rare, seek`
+ `fast (default), explore, coe, lin, quad, exploit, mmopt, rare, seek`
which you can set with e.g. `-p seek`
+Also it is recommended to set `export AFL_IMPORT_FIRST=1` to load testcases
+from other fuzzers in the campaign first.
+
You can also use different fuzzers.
If you are using afl spinoffs or afl conforming fuzzers, then just use the
same -o directory and give it a unique `-S` name.
Examples are:
+ * [Eclipser](https://github.com/SoftSec-KAIST/Eclipser/)
* [Untracer](https://github.com/FoRTE-Research/UnTracer-AFL)
* [AFLsmart](https://github.com/aflsmart/aflsmart)
* [FairFuzz](https://github.com/carolemieux/afl-rb)
@@ -607,7 +607,7 @@ Examples are:
A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
However you can also sync afl++ with honggfuzz, libfuzzer with -entropic, etc.
-Just show the main fuzzer (-M) with the `-F` option where the queue
+Just show the main fuzzer (-M) with the `-F` option where the queue/work
directory of a different fuzzer is, e.g. `-F /src/target/honggfuzz`.
#### c) The status of the fuzz campaign
@@ -672,7 +672,6 @@ switch or honggfuzz.
* Use [persistent mode](instrumentation/README.persistent_mode.md) (x2-x20 speed increase)
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [docs/env_variables.md](docs/env_variables.md)
- * Linux: Use the [afl++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase)
* Linux: Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure)
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
* Use your cores! [3.b) Using multiple cores/threads](#b-using-multiple-coresthreads)
@@ -1108,7 +1107,7 @@ without feedback, bug reports, or patches from:
Khaled Yakdan Kuang-che Wu
Josephine Calliotte Konrad Welc
Thomas Rooijakkers David Carlier
- Ruben ten Hove
+ Ruben ten Hove Joey Jiao
```
Thank you!
diff --git a/afl-cmin b/afl-cmin
index eef2b7ef..726e90ab 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -120,6 +120,7 @@ function usage() {
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
+"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
"AFL_SKIP_BIN_CHECK: skip check for target binary\n"
exit 1
diff --git a/afl-system-config b/afl-system-config
index 7031544c..456cccac 100755
--- a/afl-system-config
+++ b/afl-system-config
@@ -58,6 +58,11 @@ if [ "$PLATFORM" = "OpenBSD" ] ; then
echo 'System security features cannot be disabled on OpenBSD.'
DONE=1
fi
+if [ "$PLATFORM" = "DragonFly" ] ; then
+ echo
+ echo 'System security features cannot be disabled on DragonFly.'
+ DONE=1
+fi
if [ "$PLATFORM" = "NetBSD" ] ; then
{
#echo It is recommended to enable unprivileged users to set cpu affinity
@@ -79,5 +84,14 @@ if [ "$PLATFORM" = "Darwin" ] ; then
fi
DONE=1
fi
+if [ "$PLATFORM" = "Haiku" ] ; then
+ SETTINGS=~/config/settings/system/debug_server/settings
+ [ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
+ echo We change the debug_server default_action from user to silenty kill; \
+ [ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
+ echo Settings applied.; \
+ }
+ DONE=1
+fi
test -z "$DONE" && echo Error: Unknown platform: $PLATFORM
exit 0
diff --git a/afl-wine-trace b/afl-wine-trace
index 8853a757..63ff896b 100755
--- a/afl-wine-trace
+++ b/afl-wine-trace
@@ -28,9 +28,9 @@ if not os.getenv("AFL_INST_LIBS"):
os.environ["AFL_CODE_END"] = "0x%x" % (pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode + pe.OPTIONAL_HEADER.SizeOfCode)
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]:
- os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so")
+ os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction64.so") + ",WINEARCH=win64"
else:
- os.environ["LD_PRELOAD"] = os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so")
+ os.environ["QEMU_SET_ENV"] = "LD_PRELOAD=" + os.path.join(my_dir, "qemu_mode/unsigaction/unsigaction32.so") + ",WINEARCH=win32"
if os.getenv("WINECOV_QEMU_PATH"):
qemu_path = os.getenv("WINECOV_QEMU_PATH")
diff --git a/custom_mutators/Android.bp b/custom_mutators/Android.bp
new file mode 100644
index 00000000..89abc3e9
--- /dev/null
+++ b/custom_mutators/Android.bp
@@ -0,0 +1,115 @@
+cc_library_shared {
+ name: "libfuzzer-mutator",
+ vendor_available: true,
+ host_supported: true,
+
+ cflags: [
+ "-g",
+ "-O0",
+ "-funroll-loops",
+ "-fPIC",
+ "-fpermissive",
+ "-std=c++11",
+ ],
+
+ srcs: [
+ "libfuzzer/FuzzerCrossOver.cpp",
+ "libfuzzer/FuzzerDataFlowTrace.cpp",
+ "libfuzzer/FuzzerDriver.cpp",
+ "libfuzzer/FuzzerExtFunctionsDlsym.cpp",
+ "libfuzzer/FuzzerExtFunctionsWeak.cpp",
+ "libfuzzer/FuzzerExtFunctionsWindows.cpp",
+ "libfuzzer/FuzzerExtraCounters.cpp",
+ "libfuzzer/FuzzerFork.cpp",
+ "libfuzzer/FuzzerIO.cpp",
+ "libfuzzer/FuzzerIOPosix.cpp",
+ "libfuzzer/FuzzerIOWindows.cpp",
+ "libfuzzer/FuzzerLoop.cpp",
+ "libfuzzer/FuzzerMerge.cpp",
+ "libfuzzer/FuzzerMutate.cpp",
+ "libfuzzer/FuzzerSHA1.cpp",
+ "libfuzzer/FuzzerTracePC.cpp",
+ "libfuzzer/FuzzerUtil.cpp",
+ "libfuzzer/FuzzerUtilDarwin.cpp",
+ "libfuzzer/FuzzerUtilFuchsia.cpp",
+ "libfuzzer/FuzzerUtilLinux.cpp",
+ "libfuzzer/FuzzerUtilPosix.cpp",
+ "libfuzzer/FuzzerUtilWindows.cpp",
+ "libfuzzer/libfuzzer.cpp",
+ ],
+
+ header_libs: [
+ "libafl_headers",
+ ],
+}
+
+/*cc_library_shared {
+ name: "honggfuzz-mutator",
+ vendor_available: true,
+ host_supported: true,
+
+ cflags: [
+ "-g",
+ "-O0",
+ "-funroll-loops",
+ "-fPIC",
+ "-Wl,-Bsymbolic",
+ ],
+
+ srcs: [
+ "honggfuzz/honggfuzz.c",
+ "honggfuzz/mangle.c",
+// "../src/afl-perfomance.c",
+ ],
+
+ header_libs: [
+ "libafl_headers",
+ ],
+}*/
+
+cc_library_shared {
+ name: "radamsa-mutator",
+ vendor_available: true,
+ host_supported: true,
+
+ cflags: [
+ "-g",
+ "-O0",
+ "-funroll-loops",
+ "-fPIC",
+ ],
+
+ srcs: [
+ "radamsa/libradamsa.c",
+ "radamsa/radamsa-mutator.c",
+ ],
+
+ header_libs: [
+ "libafl_headers",
+ ],
+}
+
+cc_library_shared {
+ name: "symcc-mutator",
+ vendor_available: true,
+ host_supported: true,
+
+ cflags: [
+ "-g",
+ "-O0",
+ "-funroll-loops",
+ "-fPIC",
+ ],
+
+ srcs: [
+ "symcc/symcc.c",
+ ],
+
+ header_libs: [
+ "libafl_headers",
+ ],
+}
+
+subdirs = [
+ "libprotobuf-mutator-example",
+]
diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c
index c2988319..9c3d1ed4 100644
--- a/custom_mutators/honggfuzz/mangle.c
+++ b/custom_mutators/honggfuzz/mangle.c
@@ -995,7 +995,7 @@ void mangle_mangleContent(run_t *run, int speed_factor) {
}
- uint64_t changesCnt = run->global->mutate.mutationsPerRun;
+ uint64_t changesCnt;
if (speed_factor < 5) {
diff --git a/custom_mutators/libfuzzer/FuzzerDataFlowTrace.cpp b/custom_mutators/libfuzzer/FuzzerDataFlowTrace.cpp
index 797a52a7..489665f7 100644
--- a/custom_mutators/libfuzzer/FuzzerDataFlowTrace.cpp
+++ b/custom_mutators/libfuzzer/FuzzerDataFlowTrace.cpp
@@ -246,7 +246,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
}
- if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
+ if (FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
return false;
// Read traces.
@@ -259,8 +259,8 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
if (!CorporaHashes.count(Name)) continue; // not in the corpus.
NumTraceFiles++;
// Printf("=== %s\n", Name.c_str());
- std::ifstream IF(SF.File);
- while (std::getline(IF, L, '\n')) {
+ std::ifstream IF2(SF.File);
+ while (std::getline(IF2, L, '\n')) {
size_t FunctionNum = 0;
std::string DFTString;
@@ -314,8 +314,8 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
// we then request tags in [0,Size/2) and [Size/2, Size), and so on.
// Function number => DFT.
auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File)));
- std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
- std::unordered_set<std::string> Cov;
+// std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
+// std::unordered_set<std::string> Cov;
Command Cmd;
Cmd.addArgument(DFTBinary);
Cmd.addArgument(F.File);
diff --git a/custom_mutators/libfuzzer/FuzzerDefs.h b/custom_mutators/libfuzzer/FuzzerDefs.h
index 1a2752af..3952ac51 100644
--- a/custom_mutators/libfuzzer/FuzzerDefs.h
+++ b/custom_mutators/libfuzzer/FuzzerDefs.h
@@ -46,7 +46,7 @@ template<typename T>
fuzzer_allocator() = default;
template<class U>
- fuzzer_allocator(const fuzzer_allocator<U>&) {}
+ explicit fuzzer_allocator(const fuzzer_allocator<U>&) {}
template<class Other>
struct rebind { typedef fuzzer_allocator<Other> other; };
diff --git a/custom_mutators/libfuzzer/FuzzerDictionary.h b/custom_mutators/libfuzzer/FuzzerDictionary.h
index 301c5d9a..ddd2d2f1 100644
--- a/custom_mutators/libfuzzer/FuzzerDictionary.h
+++ b/custom_mutators/libfuzzer/FuzzerDictionary.h
@@ -49,7 +49,7 @@ typedef FixedWord<64> Word;
class DictionaryEntry {
public:
DictionaryEntry() {}
- DictionaryEntry(Word W) : W(W) {}
+ explicit DictionaryEntry(Word W) : W(W) {}
DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
const Word &GetW() const { return W; }
@@ -92,7 +92,7 @@ class Dictionary {
assert(Idx < Size);
return DE[Idx];
}
- void push_back(DictionaryEntry DE) {
+ void push_back(const DictionaryEntry &DE) {
if (Size < kMaxDictSize)
this->DE[Size++] = DE;
}
diff --git a/custom_mutators/libfuzzer/FuzzerRandom.h b/custom_mutators/libfuzzer/FuzzerRandom.h
index 659283ee..7b1e1b1d 100644
--- a/custom_mutators/libfuzzer/FuzzerRandom.h
+++ b/custom_mutators/libfuzzer/FuzzerRandom.h
@@ -16,7 +16,7 @@
namespace fuzzer {
class Random : public std::minstd_rand {
public:
- Random(unsigned int seed) : std::minstd_rand(seed) {}
+ explicit Random(unsigned int seed) : std::minstd_rand(seed) {}
result_type operator()() { return this->std::minstd_rand::operator()(); }
size_t Rand() { return this->operator()(); }
size_t RandBool() { return Rand() % 2; }
diff --git a/custom_mutators/libfuzzer/FuzzerTracePC.h b/custom_mutators/libfuzzer/FuzzerTracePC.h
index 4601300c..a58fdf8d 100644
--- a/custom_mutators/libfuzzer/FuzzerTracePC.h
+++ b/custom_mutators/libfuzzer/FuzzerTracePC.h
@@ -145,10 +145,10 @@ private:
};
Region *Regions;
size_t NumRegions;
- uint8_t *Start() { return Regions[0].Start; }
- uint8_t *Stop() { return Regions[NumRegions - 1].Stop; }
- size_t Size() { return Stop() - Start(); }
- size_t Idx(uint8_t *P) {
+ uint8_t *Start() const { return Regions[0].Start; }
+ uint8_t *Stop() const { return Regions[NumRegions - 1].Stop; }
+ size_t Size() const { return Stop() - Start(); }
+ size_t Idx(uint8_t *P) const {
assert(P >= Start() && P < Stop());
return P - Start();
}
diff --git a/custom_mutators/libprotobuf-mutator-example/Android.bp b/custom_mutators/libprotobuf-mutator-example/Android.bp
new file mode 100644
index 00000000..01f1c23e
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/Android.bp
@@ -0,0 +1,32 @@
+cc_library_shared {
+ name: "libprotobuf-mutator-example-afl",
+ vendor_available: true,
+ host_supported: true,
+
+ cflags: [
+ "-g",
+ "-O0",
+ "-fPIC",
+ "-Wall",
+ ],
+
+ srcs: [
+ "lpm_aflpp_custom_mutator_input.cc",
+ "test.proto",
+ ],
+
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ "libprotobuf-mutator",
+ ],
+}
+
+cc_binary {
+ name: "libprotobuf-mutator-vuln",
+ vendor_available: true,
+ host_supported: true,
+
+ srcs: [
+ "vuln.c",
+ ],
+}
diff --git a/custom_mutators/libprotobuf-mutator-example/README.md b/custom_mutators/libprotobuf-mutator-example/README.md
new file mode 100644
index 00000000..5a844c00
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/README.md
@@ -0,0 +1 @@
+Ported from [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/5_libprotobuf_aflpp_custom_mutator_input)
diff --git a/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.cc b/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.cc
new file mode 100644
index 00000000..e0273849
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.cc
@@ -0,0 +1,118 @@
+#include "lpm_aflpp_custom_mutator_input.h"
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+using std::cin;
+using std::cout;
+using std::endl;
+
+std::string ProtoToData(const TEST &test_proto) {
+ std::stringstream all;
+ const auto &aa = test_proto.a();
+ const auto &bb = test_proto.b();
+ all.write((const char*)&aa, sizeof(aa));
+ if(bb.size() != 0) {
+ all.write(bb.c_str(), bb.size());
+ }
+
+ std::string res = all.str();
+ if (bb.size() != 0 && res.size() != 0) {
+ // set PROTO_FUZZER_DUMP_PATH env to dump the serialized protobuf
+ if (const char *dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) {
+ std::ofstream of(dump_path);
+ of.write(res.data(), res.size());
+ }
+ }
+ return res;
+}
+
+/**
+ * Initialize this custom mutator
+ *
+ * @param[in] afl a pointer to the internal state object. Can be ignored for
+ * now.
+ * @param[in] seed A seed for this mutator - the same seed should always mutate
+ * in the same way.
+ * @return Pointer to the data object this custom mutator instance should use.
+ * There may be multiple instances of this mutator in one afl-fuzz run!
+ * Return NULL on error.
+ */
+extern "C" MyMutator *afl_custom_init(void *afl, unsigned int seed) {
+ MyMutator *mutator = new MyMutator();
+
+ mutator->RegisterPostProcessor(
+ TEST::descriptor(),
+ [](google::protobuf::Message* message, unsigned int seed) {
+ // libprotobuf-mutator's built-in mutator is kind of....crappy :P
+ // Even a dumb fuzz like `TEST.a = rand();` is better in this case... Q_Q
+ // We register a post processor to apply our dumb fuzz
+
+ TEST *t = static_cast<TEST *>(message);
+ t->set_a(rand());
+ });
+
+ srand(seed);
+ return mutator;
+}
+
+/**
+ * Perform custom mutations on a given input
+ *
+ * @param[in] data pointer returned in afl_custom_init for this fuzz case
+ * @param[in] buf Pointer to input data to be mutated
+ * @param[in] buf_size Size of input data
+ * @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
+ * error.
+ * @param[in] add_buf Buffer containing the additional test case
+ * @param[in] add_buf_size Size of the additional test case
+ * @param[in] max_size Maximum size of the mutated output. The mutation must not
+ * produce data larger than max_size.
+ * @return Size of the mutated output.
+ */
+extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_custom_init
+ uint8_t *buf, size_t buf_size, // input data to be mutated
+ uint8_t **out_buf, // output buffer
+ uint8_t *add_buf, size_t add_buf_size, // add_buf can be NULL
+ size_t max_size) {
+ // This function can be named either "afl_custom_fuzz" or "afl_custom_mutator"
+ // A simple test shows that "buf" will be the content of the current test case
+ // "add_buf" will be the next test case ( from AFL++'s input queue )
+
+ TEST input;
+ // parse input data to TEST
+ // Notice that input data should be a serialized protobuf data
+ // Check ./in/ii and test_protobuf_serializer for more detail
+ bool parse_ok = input.ParseFromArray(buf, buf_size);
+ if(!parse_ok) {
+ // Invalid serialize protobuf data. Don't mutate.
+ // Return a dummy buffer. Also mutated_size = 0
+ static uint8_t *dummy = new uint8_t[10]; // dummy buffer with no data
+ *out_buf = dummy;
+ return 0;
+ }
+ // mutate the protobuf
+ mutator->Mutate(&input, max_size);
+
+ // Convert protobuf to raw data
+ const TEST *p = &input;
+ std::string s = ProtoToData(*p);
+ // Copy to a new buffer ( mutated_out )
+ size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
+ uint8_t *mutated_out = new uint8_t[mutated_size+1];
+ memcpy(mutated_out, s.c_str(), mutated_size); // copy the mutated data
+ // Assign the mutated data and return mutated_size
+ *out_buf = mutated_out;
+ return mutated_size;
+}
+
+/**
+ * Deinitialize everything
+ *
+ * @param data The data ptr from afl_custom_init
+ */
+extern "C" void afl_custom_deinit(void *data) {
+ // Honestly I don't know what to do with this...
+ return;
+}
+
diff --git a/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.h b/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.h
new file mode 100644
index 00000000..ebd3ca65
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/lpm_aflpp_custom_mutator_input.h
@@ -0,0 +1,5 @@
+#include <src/mutator.h>
+#include "test.pb.h"
+
+class MyMutator : public protobuf_mutator::Mutator {
+};
diff --git a/custom_mutators/libprotobuf-mutator-example/test.proto b/custom_mutators/libprotobuf-mutator-example/test.proto
new file mode 100644
index 00000000..e2256c6e
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/test.proto
@@ -0,0 +1,7 @@
+syntax = "proto2";
+
+message TEST {
+ required uint32 a = 1;
+ required string b = 2;
+}
+
diff --git a/custom_mutators/libprotobuf-mutator-example/vuln.c b/custom_mutators/libprotobuf-mutator-example/vuln.c
new file mode 100644
index 00000000..8ffb7080
--- /dev/null
+++ b/custom_mutators/libprotobuf-mutator-example/vuln.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ char str[100]={};
+ read(0, str, 100);
+ int *ptr = NULL;
+ if( str[0] == '\x02' || str[0] == '\xe8') {
+ *ptr = 123;
+ }
+ return 0;
+}
+
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 71846535..60f09ca5 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -9,17 +9,24 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
-### Version ++3.01a (release)
+### Version ++3.01a (dev)
- Mac OS ARM64 support
+ - New selective instrumentation option with __AFL_COVERAGE_... commands
+ to be placed in the source code.
+ Check out instrumentation/README.instrument_list.md
- afl-fuzz
- fix crash for very, very fast targets+systems (thanks to mhlakhani
for reporting)
+ - if determinstic mode is active (-D, or -M without -d) then we sync
+ after every queue entry as this can take very long time otherwise
+ - better detection if a target needs a large shared map
- switched to a faster RNG
- added hghwng's patch for faster trace map analysis
- afl-cc
- allow instrumenting LLVMFuzzerTestOneInput
- fixed endless loop for allow/blocklist lines starting with a
comment (thanks to Zherya for reporting)
+ - cmplog/redqueen now also tracks floats/doubles
- added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard
support (less performant than our own), GCC for old afl-gcc and
CLANG for old afl-clang
@@ -28,7 +35,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
already building with all cores, the gcc plugin needs only one.
- added dummy Makefile to instrumentation/
- Updated utils/afl_frida to be 5% faster
-
+ - Added AFL_KILL_SIGNAL env variable for custom targets (thanks @v-p-b)
### Version ++3.00c (release)
- llvm_mode/ and gcc_plugin/ moved to instrumentation/
diff --git a/docs/env_variables.md b/docs/env_variables.md
index e6b9381b..26128b01 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -350,6 +350,10 @@ checks or alter some of the more exotic semantics of the tool:
- Note that `AFL_POST_LIBRARY` is deprecated, use `AFL_CUSTOM_MUTATOR_LIBRARY`
instead (see below).
+ - `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on timeout.
+ Unless you implement your own targets or instrumentation, you likely don't have to set it.
+ By default, on timeout and on exit, `SIGKILL` (`AFL_KILL_SIGNAL=9`) will be delivered to the child.
+
- Setting `AFL_CUSTOM_MUTATOR_LIBRARY` to a shared library with
afl_custom_fuzz() creates additional mutations through this library.
If afl-fuzz is compiled with Python (which is autodetected during builing
diff --git a/docs/power_schedules.md b/docs/power_schedules.md
index 06fefa12..493f9609 100644
--- a/docs/power_schedules.md
+++ b/docs/power_schedules.md
@@ -13,8 +13,8 @@ We find that AFL's exploitation-based constant schedule assigns **too much energ
| AFL flag | Power Schedule |
| ------------- | -------------------------- |
-| `-p explore` (default)| ![EXPLORE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D) |
-| `-p fast` | ![FAST](http://latex.codecogs.com/gif.latex?p(i)=\\min\\left(\\frac{\\alpha(i)}{\\beta}\\cdot\\frac{2^{s(i)}}{f(i)},M\\right)) |
+| `-p explore` | ![EXPLORE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D) |
+| `-p fast` (default)| ![FAST](http://latex.codecogs.com/gif.latex?p(i)=\\min\\left(\\frac{\\alpha(i)}{\\beta}\\cdot\\frac{2^{s(i)}}{f(i)},M\\right)) |
| `-p coe` | ![COE](http://latex.codecogs.com/gif.latex?p%28i%29%3D%5Cbegin%7Bcases%7D%200%20%26%20%5Ctext%7B%20if%20%7D%20f%28i%29%20%3E%20%5Cmu%5C%5C%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%202%5E%7Bs%28i%29%7D%2C%20M%5Cright%29%20%26%20%5Ctext%7B%20otherwise.%7D%20%5Cend%7Bcases%7D) |
| `-p quad` | ![QUAD](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%5Cfrac%7Bs%28i%29%5E2%7D%7Bf%28i%29%7D%2CM%5Cright%29) |
| `-p lin` | ![LIN](http://latex.codecogs.com/gif.latex?p%28i%29%20%3D%20%5Cmin%5Cleft%28%5Cfrac%7B%5Calpha%28i%29%7D%7B%5Cbeta%7D%5Ccdot%5Cfrac%7Bs%28i%29%7D%7Bf%28i%29%7D%2CM%5Cright%29) |
diff --git a/docs/status_screen.md b/docs/status_screen.md
index 0cede6ff..0329d960 100644
--- a/docs/status_screen.md
+++ b/docs/status_screen.md
@@ -29,13 +29,18 @@ With that out of the way, let's talk about what's actually on the screen...
### The status bar
+```
+american fuzzy lop ++3.01a (default) [fast] {0}
+```
+
The top line shows you which mode afl-fuzz is running in
(normal: "american fuzy lop", crash exploration mode: "peruvian rabbit mode")
and the version of afl++.
Next to the version is the banner, which, if not set with -T by hand, will
either show the binary name being fuzzed, or the -M/-S main/secondary name for
parallel fuzzing.
-Finally, the last item is the power schedule mode being run (default: explore).
+Second to last is the power schedule mode being run (default: fast).
+Finally, the last item is the CPU id.
### Process timing
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 0bf0aebe..6342c8b6 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -37,10 +37,6 @@
#define _FILE_OFFSET_BITS 64
#endif
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
-
#include "config.h"
#include "types.h"
#include "debug.h"
@@ -381,7 +377,7 @@ typedef struct afl_env_vars {
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
- *afl_testcache_entries;
+ *afl_testcache_entries, *afl_kill_signal;
} afl_env_vars_t;
@@ -573,7 +569,7 @@ typedef struct afl_state {
u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */
- s32 stage_cur, stage_max; /* Stage progression */
+ u32 stage_cur, stage_max; /* Stage progression */
s32 splicing_with; /* Splicing with which test case? */
u32 main_node_id, main_node_max; /* Main instance job splitting */
@@ -590,9 +586,9 @@ typedef struct afl_state {
u32 rand_cnt; /* Random number counter */
-/* unsigned long rand_seed[3]; would also work */
+ /* unsigned long rand_seed[3]; would also work */
AFL_RAND_RETURN rand_seed[3];
- s64 init_seed;
+ s64 init_seed;
u64 total_cal_us, /* Total calibration time (us) */
total_cal_cycles; /* Total calibration cycles */
@@ -645,10 +641,10 @@ typedef struct afl_state {
unsigned long long int last_avg_exec_update;
u32 last_avg_execs;
- float last_avg_execs_saved;
+ double last_avg_execs_saved;
/* foreign sync */
-#define FOREIGN_SYNCS_MAX 32
+#define FOREIGN_SYNCS_MAX 32U
u8 foreign_sync_cnt;
struct foreign_sync foreign_syncs[FOREIGN_SYNCS_MAX];
diff --git a/include/android-ashmem.h b/include/android-ashmem.h
index 41d4d2da..6939e06d 100644
--- a/include/android-ashmem.h
+++ b/include/android-ashmem.h
@@ -1,112 +1,81 @@
-/*
- american fuzzy lop++ - android shared memory compatibility layer
- ----------------------------------------------------------------
-
- Originally written by Michal Zalewski
-
- Now maintained by Marc Heuse <mh@mh-sec.de>,
- Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
- Andrea Fioraldi <andreafioraldi@gmail.com>,
- Dominik Maier <mail@dmnk.co>
-
- Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- This header re-defines the shared memory routines used by AFL++
- using the Andoid API.
-
- */
-
+#ifdef __ANDROID__
#ifndef _ANDROID_ASHMEM_H
#define _ANDROID_ASHMEM_H
-#ifdef __ANDROID__
-
- #include <fcntl.h>
- #include <linux/shm.h>
- #include <linux/ashmem.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
-
- #if __ANDROID_API__ >= 26
- #define shmat bionic_shmat
- #define shmctl bionic_shmctl
- #define shmdt bionic_shmdt
- #define shmget bionic_shmget
- #endif
-
- #include <sys/shm.h>
- #undef shmat
- #undef shmctl
- #undef shmdt
- #undef shmget
- #include <stdio.h>
+#include <fcntl.h>
+#include <linux/ashmem.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
- #define ASHMEM_DEVICE "/dev/ashmem"
+#if __ANDROID_API__ >= 26
+#define shmat bionic_shmat
+#define shmctl bionic_shmctl
+#define shmdt bionic_shmdt
+#define shmget bionic_shmget
+#endif
+#include <sys/shm.h>
+#undef shmat
+#undef shmctl
+#undef shmdt
+#undef shmget
+#include <stdio.h>
-static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
+#define ASHMEM_DEVICE "/dev/ashmem"
+int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
int ret = 0;
if (__cmd == IPC_RMID) {
-
- int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
- struct ashmem_pin pin = {0, (unsigned int)length};
+ int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
+ struct ashmem_pin pin = {0, length};
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
close(__shmid);
-
}
return ret;
-
}
-static inline int shmget(key_t __key, size_t __size, int __shmflg) {
-
- (void)__shmflg;
- int fd, ret;
+int shmget(key_t __key, size_t __size, int __shmflg) {
+ (void) __shmflg;
+ int fd, ret;
char ourkey[11];
fd = open(ASHMEM_DEVICE, O_RDWR);
- if (fd < 0) return fd;
+ if (fd < 0)
+ return fd;
sprintf(ourkey, "%d", __key);
ret = ioctl(fd, ASHMEM_SET_NAME, ourkey);
- if (ret < 0) goto error;
+ if (ret < 0)
+ goto error;
ret = ioctl(fd, ASHMEM_SET_SIZE, __size);
- if (ret < 0) goto error;
+ if (ret < 0)
+ goto error;
return fd;
error:
close(fd);
return ret;
-
}
-static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
-
- (void)__shmflg;
- int size;
+void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
+ (void) __shmflg;
+ int size;
void *ptr;
size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
- if (size < 0) { return NULL; }
+ if (size < 0) {
+ return NULL;
+ }
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
- if (ptr == MAP_FAILED) { return NULL; }
+ if (ptr == MAP_FAILED) {
+ return NULL;
+ }
return ptr;
-
}
-#endif /* __ANDROID__ */
-
-#endif
-
+#endif /* !_ANDROID_ASHMEM_H */
+#endif /* !__ANDROID__ */
diff --git a/include/common.h b/include/common.h
index 125c3abf..9490ec5f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -56,6 +56,11 @@ extern u8 *doc_path; /* path to documentation dir */
u8 *find_binary(u8 *fname);
+/* Parses the kill signal environment variable, FATALs on error.
+ If the env is not set, sets the env to default_signal for the signal handlers
+ and returns the default_signal. */
+int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal);
+
/* Read a bitmap from file fname to memory
This is for the -B option again. */
diff --git a/include/config.h b/include/config.h
index e8a49270..973bbcbb 100644
--- a/include/config.h
+++ b/include/config.h
@@ -80,11 +80,11 @@
/* Default timeout for fuzzed code (milliseconds). This is the upper bound,
also used for detecting hangs; the actual value is auto-scaled: */
-#define EXEC_TIMEOUT 1000
+#define EXEC_TIMEOUT 1000U
/* Timeout rounding factor when auto-scaling (milliseconds): */
-#define EXEC_TM_ROUND 20
+#define EXEC_TM_ROUND 20U
/* 64bit arch MACRO */
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
@@ -93,48 +93,48 @@
/* Default memory limit for child process (MB) 0 = disabled : */
-#define MEM_LIMIT 0
+#define MEM_LIMIT 0U
/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */
-#define MEM_LIMIT_QEMU 0
+#define MEM_LIMIT_QEMU 0U
/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */
-#define MEM_LIMIT_UNICORN 0
+#define MEM_LIMIT_UNICORN 0U
/* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */
-#define CAL_CYCLES 8
-#define CAL_CYCLES_LONG 40
+#define CAL_CYCLES 8U
+#define CAL_CYCLES_LONG 40U
/* Number of subsequent timeouts before abandoning an input file: */
-#define TMOUT_LIMIT 250
+#define TMOUT_LIMIT 250U
/* Maximum number of unique hangs or crashes to record: */
-#define KEEP_UNIQUE_HANG 500
-#define KEEP_UNIQUE_CRASH 5000
+#define KEEP_UNIQUE_HANG 500U
+#define KEEP_UNIQUE_CRASH 5000U
/* Baseline number of random tweaks during a single 'havoc' stage: */
-#define HAVOC_CYCLES 256
-#define HAVOC_CYCLES_INIT 1024
+#define HAVOC_CYCLES 256U
+#define HAVOC_CYCLES_INIT 1024U
/* Maximum multiplier for the above (should be a power of two, beware
of 32-bit int overflows): */
-#define HAVOC_MAX_MULT 64
-#define HAVOC_MAX_MULT_MOPT 64
+#define HAVOC_MAX_MULT 64U
+#define HAVOC_MAX_MULT_MOPT 64U
/* Absolute minimum number of havoc cycles (after all adjustments): */
-#define HAVOC_MIN 12
+#define HAVOC_MIN 12U
/* Power Schedule Divisor */
-#define POWER_BETA 1
+#define POWER_BETA 1U
#define MAX_FACTOR (POWER_BETA * 32)
/* Maximum stacking for havoc-stage tweaks. The actual value is calculated
@@ -146,19 +146,19 @@
In other words, the default (n = 4) produces 2, 4, 8, 16
stacked tweaks: */
-#define HAVOC_STACK_POW2 4
+#define HAVOC_STACK_POW2 4U
/* Caps on block sizes for cloning and deletion operations. Each of these
ranges has a 33% probability of getting picked, except for the first
two cycles where smaller blocks are favored: */
-#define HAVOC_BLK_SMALL 32
-#define HAVOC_BLK_MEDIUM 128
-#define HAVOC_BLK_LARGE 1500
+#define HAVOC_BLK_SMALL 32U
+#define HAVOC_BLK_MEDIUM 128U
+#define HAVOC_BLK_LARGE 1500U
/* Extra-large blocks, selected very rarely (<5% of the time): */
-#define HAVOC_BLK_XL 32768
+#define HAVOC_BLK_XL 32768U
/* Probabilities of skipping non-favored entries in the queue, expressed as
percentages: */
@@ -186,9 +186,11 @@
#define TRIM_START_STEPS 16
#define TRIM_END_STEPS 1024
-/* Maximum size of input file, in bytes (keep under 100MB): */
+/* Maximum size of input file, in bytes (keep under 100MB, default 1MB):
+ (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c
+ and afl-fuzz-state.c have to be changed as well! */
-#define MAX_FILE (1 * 1024 * 1024)
+#define MAX_FILE (1 * 1024 * 1024U)
/* The same, for the test case minimizer: */
@@ -380,7 +382,7 @@
after changing this - otherwise, SEGVs may ensue. */
#define MAP_SIZE_POW2 16
-#define MAP_SIZE (1 << MAP_SIZE_POW2)
+#define MAP_SIZE (1U << MAP_SIZE_POW2)
/* Maximum allocator request size (keep well under INT_MAX): */
diff --git a/include/debug.h b/include/debug.h
index 7f4a6be1..ef5b195b 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -295,7 +295,7 @@ static inline const char *colorfilter(const char *x) {
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
- SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
+ SAYF(cLRD "\n Location : " cRST "%s(), %s:%d\n\n", __func__, \
__FILE__, __LINE__); \
exit(1); \
\
@@ -308,7 +308,7 @@ static inline const char *colorfilter(const char *x) {
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
- SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
+ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%d\n\n", __func__, \
__FILE__, __LINE__); \
abort(); \
\
@@ -322,7 +322,7 @@ static inline const char *colorfilter(const char *x) {
fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \
- SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
+ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%d\n", __func__, \
__FILE__, __LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
exit(1); \
diff --git a/include/envs.h b/include/envs.h
index e4e49c4d..97367fae 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -61,6 +61,7 @@ static char *afl_environment_variables[] = {
"AFL_IMPORT_FIRST",
"AFL_INST_LIBS",
"AFL_INST_RATIO",
+ "AFL_KILL_SIGNAL",
"AFL_KEEP_TRACES",
"AFL_KEEP_ASSEMBLY",
"AFL_LD_HARD_FAIL",
diff --git a/include/forkserver.h b/include/forkserver.h
index 8e029266..3019e289 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -99,6 +99,8 @@ typedef struct afl_forkserver {
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
+ u8 kill_signal;
+
} afl_forkserver_t;
typedef enum fsrv_run_result {
diff --git a/include/types.h b/include/types.h
index 39f599a0..3e3bc953 100644
--- a/include/types.h
+++ b/include/types.h
@@ -50,7 +50,7 @@ typedef uint32_t u32;
#define FS_OPT_SHDMEM_FUZZ 0x01000000
#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
-#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1)
+#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
#define FS_OPT_SET_MAPSIZE(x) \
(x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1))
diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc
index 6b3231e6..235ee30f 100644
--- a/instrumentation/LLVMInsTrim.so.cc
+++ b/instrumentation/LLVMInsTrim.so.cc
@@ -200,7 +200,7 @@ struct InsTrim : public ModulePass {
LoadInst * PrevCtx = NULL; // for CTX sensitive coverage
if (ctx_str)
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__HAIKU__)
AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
#else
@@ -211,7 +211,7 @@ struct InsTrim : public ModulePass {
#ifdef AFL_HAVE_VECTOR_INTRINSICS
if (ngram_size)
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
/* Initializer */ nullptr, "__afl_prev_loc");
@@ -224,7 +224,7 @@ struct InsTrim : public ModulePass {
#endif
else
#endif
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
#else
@@ -407,10 +407,10 @@ struct InsTrim : public ModulePass {
// does the function have calls? and is any of the calls larger than
// one basic block?
has_calls = 0;
- for (auto &BB : F) {
+ for (auto &BB2 : F) {
if (has_calls) break;
- for (auto &IN : BB) {
+ for (auto &IN : BB2) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
@@ -454,7 +454,7 @@ struct InsTrim : public ModulePass {
auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
DenseMap<BasicBlock *, unsigned> PredMap;
- for (auto PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
+ for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
BasicBlock *PBB = *PI;
auto It = PredMap.insert({PBB, genLabel()});
@@ -568,7 +568,7 @@ struct InsTrim : public ModulePass {
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
- OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr,
+ OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
total_rs, total_hs, modeline);
}
diff --git a/instrumentation/MarkNodes.cc b/instrumentation/MarkNodes.cc
index 20a7df35..b77466d9 100644
--- a/instrumentation/MarkNodes.cc
+++ b/instrumentation/MarkNodes.cc
@@ -332,11 +332,11 @@ bool Indistinguish(uint32_t node1, uint32_t node2) {
void MakeUniq(uint32_t now) {
- bool StopFlag = false;
if (Marked.find(now) == Marked.end()) {
for (uint32_t pred1 : t_Pred[now]) {
+ bool StopFlag = false;
for (uint32_t pred2 : t_Pred[now]) {
if (pred1 == pred2) continue;
diff --git a/instrumentation/README.instrument_list.md b/instrumentation/README.instrument_list.md
index 122be2b6..b47b50f6 100644
--- a/instrumentation/README.instrument_list.md
+++ b/instrumentation/README.instrument_list.md
@@ -1,8 +1,9 @@
# Using afl++ with partial instrumentation
- This file describes how to selectively instrument only source files
- or functions that are of interest to you using the LLVM and GCC_PLUGIN
- instrumentation provided by afl++.
+ This file describes two different mechanisms to selectively instrument
+ only specific parts in the target.
+
+ Both mechanisms work for LLVM and GCC_PLUGIN, but not for afl-clang/afl-gcc.
## 1) Description and purpose
@@ -12,28 +13,42 @@ the program, leaving the rest uninstrumented. This helps to focus the fuzzer
on the important parts of the program, avoiding undesired noise and
disturbance by uninteresting code being exercised.
-For this purpose, a "partial instrumentation" support en par with llvm sancov
-is provided by afl++ that allows to specify on a source file and function
-level which function should be compiled with or without instrumentation.
+For this purpose, "partial instrumentation" support is provided by afl++ that
+allows to specify what should be instrumented and what not.
+
+Both mechanisms can be used together.
+
+## 2) Selective instrumentation with __AFL_COVERAGE_... directives
+
+In this mechanism the selective instrumentation is done in the source code.
-Note: When using PCGUARD mode - and llvm 12+ - you can use this instead:
-https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
+After the includes a special define has to be made, eg.:
+
+```
+#include <stdio.h>
+#include <stdint.h>
+// ...
+
+__AFL_COVERAGE(); // <- required for this feature to work
+```
-The llvm sancov list format is fully supported by afl++, however afl++ has
-more flexibility.
+If you want to disable the coverage at startup until you specify coverage
+should be started, then add `__AFL_COVERAGE_START_OFF();` at that position.
-## 2a) Building the LLVM module
+From here on out you have the following macros available that you can use
+in any function where you want:
-The new code is part of the existing afl++ LLVM module in the instrumentation/
-subdirectory. There is nothing specifically to do for the build :)
+ * `__AFL_COVERAGE_ON();` - enable coverage from this point onwards
+ * `__AFL_COVERAGE_OFF();` - disable coverage from this point onwards
+ * `__AFL_COVERAGE_DISCARD();` - reset all coverage gathered until this point
+ * `__AFL_COVERAGE_SKIP();` - mark this test case as unimportant. Whatever happens, afl-fuzz will ignore it.
-## 2b) Building the GCC module
+## 3) Selective instrumenation with AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST
-The new code is part of the existing afl++ GCC_PLUGIN module in the
-instrumentation/ subdirectory. There is nothing specifically to do for
-the build :)
+This feature is equivalent to llvm 12 sancov feature and allows to specify
+on a filename and/or function name level to instrument these or skip them.
-## 3) How to use the partial instrumentation mode
+### 3a) How to use the partial instrumentation mode
In order to build with partial instrumentation, you need to build with
afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++.
@@ -90,7 +105,7 @@ fun: MallocFoo
```
Note that whitespace is ignored and comments (`# foo`) are supported.
-## 4) UNIX-style pattern matching
+### 3b) UNIX-style pattern matching
You can add UNIX-style pattern matching in the "instrument file list" entries.
See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 82e55218..016ac71f 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -1111,7 +1111,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations with no collisions (on average %llu "
- "collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
+ "collisions would be in afl-gcc/vanilla AFL) (%s mode).",
inst, calculateCollisions(inst), modeline);
}
@@ -1403,24 +1403,17 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock();
- DebugLoc EntryLoc;
+
if (IsEntryBB) {
- if (auto SP = F.getSubprogram())
- EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before
// calls.
IP = PrepareToSplitEntryBlock(BB, IP);
- } else {
-
- EntryLoc = IP->getDebugLoc();
-
}
IRBuilder<> IRB(&*IP);
- IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC)
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 102b44a4..ecd6bc9b 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -1163,24 +1163,18 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock();
- DebugLoc EntryLoc;
+
if (IsEntryBB) {
- if (auto SP = F.getSubprogram())
- EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before
// calls.
IP = PrepareToSplitEntryBlock(BB, IP);
- } else {
-
- EntryLoc = IP->getDebugLoc();
-
}
IRBuilder<> IRB(&*IP);
- IRB.SetCurrentDebugLocation(EntryLoc);
+
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC);
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index cddde87c..e31bff16 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -76,7 +76,9 @@
#endif
u8 __afl_area_initial[MAP_INITIAL_SIZE];
+u8 * __afl_area_ptr_dummy = __afl_area_initial;
u8 * __afl_area_ptr = __afl_area_initial;
+u8 * __afl_area_ptr_backup = __afl_area_initial;
u8 * __afl_dictionary;
u8 * __afl_fuzz_ptr;
u32 __afl_fuzz_len_dummy;
@@ -87,7 +89,12 @@ u32 __afl_map_size = MAP_SIZE;
u32 __afl_dictionary_len;
u64 __afl_map_addr;
-#ifdef __ANDROID__
+// for the __AFL_COVERAGE_ON/__AFL_COVERAGE_OFF features to work:
+int __afl_selective_coverage __attribute__((weak));
+int __afl_selective_coverage_start_off __attribute__((weak));
+int __afl_selective_coverage_temp = 1;
+
+#if defined(__ANDROID__) || defined(__HAIKU__)
PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
u32 __afl_prev_ctx;
u32 __afl_cmp_counter;
@@ -100,6 +107,7 @@ __thread u32 __afl_cmp_counter;
int __afl_sharedmem_fuzzing __attribute__((weak));
struct cmp_map *__afl_cmp_map;
+struct cmp_map *__afl_cmp_map_backup;
/* Child pid? */
@@ -230,7 +238,7 @@ static void __afl_map_shm_fuzz() {
static void __afl_map_shm(void) {
// if we are not running in afl ensure the map exists
- if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; }
+ if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_ptr_dummy; }
char *id_str = getenv(SHM_ENV_VAR);
@@ -295,11 +303,17 @@ static void __afl_map_shm(void) {
if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
- if (__afl_map_addr)
+ if (__afl_map_addr) {
+
munmap((void *)__afl_map_addr, __afl_final_loc);
- else
+
+ } else {
+
free(__afl_area_ptr);
- __afl_area_ptr = __afl_area_initial;
+
+ }
+
+ __afl_area_ptr = __afl_area_ptr_dummy;
}
@@ -352,6 +366,18 @@ static void __afl_map_shm(void) {
#else
u32 shm_id = atoi(id_str);
+ if (__afl_map_size && __afl_map_size > MAP_SIZE) {
+
+ u8 *map_env = getenv("AFL_MAP_SIZE");
+ if (!map_env || atoi(map_env) < MAP_SIZE) {
+
+ send_forkserver_error(FS_ERROR_MAP_SIZE);
+ _exit(1);
+
+ }
+
+ }
+
__afl_area_ptr = shmat(shm_id, (void *)__afl_map_addr, 0);
/* Whooooops. */
@@ -396,9 +422,42 @@ static void __afl_map_shm(void) {
free(__afl_area_ptr);
__afl_area_ptr = NULL;
- if (__afl_final_loc > MAP_INITIAL_SIZE)
+
+ if (__afl_final_loc > MAP_INITIAL_SIZE) {
+
__afl_area_ptr = malloc(__afl_final_loc);
- if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+
+ }
+
+ if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_ptr_dummy; }
+
+ }
+
+ __afl_area_ptr_backup = __afl_area_ptr;
+
+ if (__afl_selective_coverage) {
+
+ if (__afl_map_size > MAP_INITIAL_SIZE) {
+
+ __afl_area_ptr_dummy = malloc(__afl_map_size);
+
+ if (__afl_area_ptr_dummy) {
+
+ if (__afl_selective_coverage_start_off) {
+
+ __afl_area_ptr = __afl_area_ptr_dummy;
+
+ }
+
+ } else {
+
+ fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
+ __afl_selective_coverage = 0;
+ // continue;
+
+ }
+
+ }
}
@@ -449,6 +508,8 @@ static void __afl_map_shm(void) {
__afl_cmp_map = shmat(shm_id, NULL, 0);
#endif
+ __afl_cmp_map_backup = __afl_cmp_map;
+
if (!__afl_cmp_map || __afl_cmp_map == (void *)-1) {
perror("shmat for cmplog");
@@ -683,7 +744,7 @@ static void __afl_start_forkserver(void) {
#endif
u8 tmp[4] = {0, 0, 0, 0};
- u32 status = 0;
+ u32 status_for_fsrv = 0;
u32 already_read_first = 0;
u32 was_killed;
@@ -691,17 +752,26 @@ static void __afl_start_forkserver(void) {
void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL);
- if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
- status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
- if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT;
- if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
- if (status) status |= (FS_OPT_ENABLED);
- memcpy(tmp, &status, 4);
+ if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) {
+
+ status_for_fsrv |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
+
+ }
+
+ if (__afl_dictionary_len && __afl_dictionary) {
+
+ status_for_fsrv |= FS_OPT_AUTODICT;
+
+ }
+
+ if (__afl_sharedmem_fuzzing != 0) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
+ if (status_for_fsrv) { status_for_fsrv |= (FS_OPT_ENABLED); }
+ memcpy(tmp, &status_for_fsrv, 4);
/* 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 (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
+ if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
@@ -726,7 +796,6 @@ static void __afl_start_forkserver(void) {
// great lets pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
- s32 ret;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
@@ -738,6 +807,7 @@ static void __afl_start_forkserver(void) {
while (len != 0) {
+ s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
if (ret < 1) {
@@ -894,6 +964,8 @@ int __afl_persistent_loop(unsigned int max_cnt) {
cycle_cnt = max_cnt;
first_pass = 0;
+ __afl_selective_coverage_temp = 1;
+
return 1;
}
@@ -906,6 +978,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
__afl_area_ptr[0] = 1;
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
+ __afl_selective_coverage_temp = 1;
return 1;
@@ -915,7 +988,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
follows the loop is not traced. We do that by pivoting back to the
dummy output region. */
- __afl_area_ptr = __afl_area_initial;
+ __afl_area_ptr = __afl_area_ptr_dummy;
}
@@ -937,7 +1010,7 @@ void __afl_manual_init(void) {
init_done = 1;
is_persistent = 0;
__afl_sharedmem_fuzzing = 0;
- if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial;
+ if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_ptr_dummy;
if (getenv("AFL_DEBUG"))
fprintf(stderr,
@@ -998,7 +1071,12 @@ __attribute__((constructor(1))) void __afl_auto_second(void) {
else
ptr = (u8 *)malloc(__afl_final_loc);
- if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+ if (ptr && (ssize_t)ptr != -1) {
+
+ __afl_area_ptr = ptr;
+ __afl_area_ptr_backup = __afl_area_ptr;
+
+ }
}
@@ -1014,7 +1092,12 @@ __attribute__((constructor(0))) void __afl_auto_first(void) {
ptr = (u8 *)malloc(1024000);
- if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+ if (ptr && (ssize_t)ptr != -1) {
+
+ __afl_area_ptr = ptr;
+ __afl_area_ptr_backup = __afl_area_ptr;
+
+ }
}
@@ -1304,3 +1387,69 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
}
+/* COVERAGE manipulation features */
+
+// this variable is then used in the shm setup to create an additional map
+// if __afl_map_size > MAP_SIZE or cmplog is used.
+// Especially with cmplog this would result in a ~260MB mem increase per
+// target run.
+
+// disable coverage from this point onwards until turned on again
+void __afl_coverage_off() {
+
+ if (likely(__afl_selective_coverage)) {
+
+ __afl_area_ptr = __afl_area_ptr_dummy;
+ __afl_cmp_map = NULL;
+
+ }
+
+}
+
+// enable coverage
+void __afl_coverage_on() {
+
+ if (likely(__afl_selective_coverage && __afl_selective_coverage_temp)) {
+
+ __afl_area_ptr = __afl_area_ptr_backup;
+ __afl_cmp_map = __afl_cmp_map_backup;
+
+ }
+
+}
+
+// discard all coverage up to this point
+void __afl_coverage_discard() {
+
+ memset(__afl_area_ptr_backup, 0, __afl_map_size);
+ __afl_area_ptr_backup[0] = 1;
+
+ if (__afl_cmp_map) { memset(__afl_cmp_map, 0, sizeof(struct cmp_map)); }
+
+}
+
+// discard the testcase
+void __afl_coverage_skip() {
+
+ __afl_coverage_discard();
+
+ if (likely(is_persistent && __afl_selective_coverage)) {
+
+ __afl_coverage_off();
+ __afl_selective_coverage_temp = 0;
+
+ } else {
+
+ exit(0);
+
+ }
+
+}
+
+// mark this area as especially interesting
+void __afl_coverage_interesting(u8 val, u32 id) {
+
+ __afl_area_ptr[id] = val;
+
+}
+
diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc
index 25437609..41bb5152 100644
--- a/instrumentation/afl-gcc-pass.so.cc
+++ b/instrumentation/afl-gcc-pass.so.cc
@@ -228,7 +228,7 @@ struct afl_pass : gimple_opt_pass {
const bool neverZero;
/* Count instrumented blocks. */
- int inst_blocks;
+ unsigned int inst_blocks;
virtual unsigned int execute(function *fn) {
@@ -444,8 +444,10 @@ struct afl_pass : gimple_opt_pass {
DECL_EXTERNAL(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
TREE_STATIC(decl) = 1;
+#if !defined(__ANDROID__) && !defined(__HAIKU__)
set_decl_tls_model(
decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC));
+#endif
return decl;
}
@@ -920,8 +922,9 @@ int plugin_init(struct plugin_name_args * info,
struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version))
- FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"),
- GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR);
+ FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
+ "is %s"),
+ gcc_version.basever, version->basever);
/* Show a banner. */
bool quiet = false;
@@ -931,7 +934,7 @@ int plugin_init(struct plugin_name_args * info,
quiet = true;
/* Decide instrumentation ratio. */
- int inst_ratio = 100;
+ unsigned int inst_ratio = 100U;
if (char *inst_ratio_str = getenv("AFL_INST_RATIO"))
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
inst_ratio > 100)
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index bd8eb27a..a4b33732 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -355,7 +355,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1);
std::string Str1, Str2;
StringRef TmpStr;
- bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
+ bool HasStr1;
+ getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) {
HasStr1 = false;
@@ -367,7 +368,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
}
- bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
+ bool HasStr2;
+ getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) {
HasStr2 = false;
diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc
index 9e026e57..13dca8c4 100644
--- a/instrumentation/afl-llvm-lto-instrumentation.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc
@@ -70,7 +70,7 @@ class AFLLTOPass : public ModulePass {
if (getenv("AFL_DEBUG")) debug = 1;
if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
if ((afl_global_id = atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE)
- FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %d\n",
+ FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %u\n",
ptr, MAP_SIZE - 1);
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
@@ -100,9 +100,9 @@ class AFLLTOPass : public ModulePass {
bool AFLLTOPass::runOnModule(Module &M) {
- LLVMContext & C = M.getContext();
- std::vector<std::string> dictionary;
- std::vector<CallInst *> calls;
+ LLVMContext & C = M.getContext();
+ std::vector<std::string> dictionary;
+ // std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap;
std::vector<BasicBlock *> BlockList;
char * ptr;
@@ -471,7 +471,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1);
std::string Str1, Str2;
StringRef TmpStr;
- bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
+ bool HasStr1;
+ getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) {
HasStr1 = false;
@@ -483,7 +484,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
- bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
+ bool HasStr2;
+ getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) {
HasStr2 = false;
@@ -671,7 +673,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (!be_quiet) {
- std::string outstring;
fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
thestring.length());
for (uint8_t i = 0; i < thestring.length(); i++) {
@@ -799,7 +800,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (documentFile) {
- fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n",
+ fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%d\n",
moduleID, F.getName().str().c_str(), afl_global_id);
}
@@ -871,10 +872,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
while ((map = map >> 1))
pow2map++;
WARNF(
- "We have %u blocks to instrument but the map size is only %u. Either "
- "edit config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
+ "We have %d blocks to instrument but the map size is only %u. Either "
+ "edit config.h and set MAP_SIZE_POW2 from %d to %u, then recompile "
"afl-fuzz and llvm_mode and then make this target - or set "
- "AFL_MAP_SIZE with at least size %u when running afl-fuzz with this "
+ "AFL_MAP_SIZE with at least size %d when running afl-fuzz with this "
"target.",
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id);
@@ -937,8 +938,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (dictionary.size()) {
- size_t memlen = 0, count = 0, offset = 0;
- char * ptr;
+ size_t memlen = 0, count = 0;
// sort and unique the dictionary
std::sort(dictionary.begin(), dictionary.end());
@@ -953,14 +953,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
if (!be_quiet)
- printf("AUTODICTIONARY: %lu string%s found\n", count,
+ printf("AUTODICTIONARY: %zu string%s found\n", count,
count == 1 ? "" : "s");
if (count) {
if ((ptr = (char *)malloc(memlen + count)) == NULL) {
- fprintf(stderr, "Error: malloc for %lu bytes failed!\n",
+ fprintf(stderr, "Error: malloc for %zu bytes failed!\n",
memlen + count);
exit(-1);
@@ -968,6 +968,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
count = 0;
+ size_t offset = 0;
for (auto token : dictionary) {
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
@@ -1031,8 +1032,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
- OKF("Instrumented %u locations with no collisions (on average %llu "
- "collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
+ OKF("Instrumented %d locations with no collisions (on average %llu "
+ "collisions would be in afl-gcc/vanilla AFL) (%s mode).",
inst_blocks, calculateCollisions(inst_blocks), modeline);
}
diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc
index 8c8c987a..57ff3b47 100644
--- a/instrumentation/afl-llvm-pass.so.cc
+++ b/instrumentation/afl-llvm-pass.so.cc
@@ -241,7 +241,7 @@ bool AFLCoverage::runOnModule(Module &M) {
GlobalVariable *AFLContext = NULL;
if (ctx_str)
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__HAIKU__)
AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
#else
@@ -252,7 +252,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#ifdef AFL_HAVE_VECTOR_INTRINSICS
if (ngram_size)
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
/* Initializer */ nullptr, "__afl_prev_loc");
@@ -265,7 +265,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#endif
else
#endif
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
#else
@@ -327,10 +327,10 @@ bool AFLCoverage::runOnModule(Module &M) {
// does the function have calls? and is any of the calls larger than one
// basic block?
- for (auto &BB : F) {
+ for (auto &BB_2 : F) {
if (has_calls) break;
- for (auto &IN : BB) {
+ for (auto &IN : BB_2) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
@@ -628,7 +628,7 @@ bool AFLCoverage::runOnModule(Module &M) {
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
- OKF("Instrumented %u locations (%s mode, ratio %u%%).", inst_blocks,
+ OKF("Instrumented %d locations (%s mode, ratio %u%%).", inst_blocks,
modeline, inst_ratio);
}
diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc
index 9921de0c..3499ccf0 100644
--- a/instrumentation/cmplog-instructions-pass.cc
+++ b/instrumentation/cmplog-instructions-pass.cc
@@ -186,16 +186,19 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
selectcmpInst->getPredicate() == CmpInst::ICMP_UGE ||
selectcmpInst->getPredicate() == CmpInst::ICMP_SGE ||
selectcmpInst->getPredicate() == CmpInst::ICMP_ULE ||
- selectcmpInst->getPredicate() == CmpInst::ICMP_SLE) {
-
- auto op0 = selectcmpInst->getOperand(0);
- auto op1 = selectcmpInst->getOperand(1);
-
- IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
- IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType());
-
- /* this is probably not needed but we do it anyway */
- if (!intTyOp0 || !intTyOp1) { continue; }
+ selectcmpInst->getPredicate() == CmpInst::ICMP_SLE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_ULE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_OLT ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_ONE) {
icomps.push_back(selectcmpInst);
@@ -221,16 +224,66 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
auto op0 = selectcmpInst->getOperand(0);
auto op1 = selectcmpInst->getOperand(1);
- IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType());
- IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+ IntegerType * intTyOp0 = NULL;
+ IntegerType * intTyOp1 = NULL;
+ unsigned max_size = 0;
+ std::vector<Value *> args;
- unsigned max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
- ? intTyOp0->getBitWidth()
- : intTyOp1->getBitWidth();
+ if (selectcmpInst->getOpcode() == Instruction::FCmp) {
- std::vector<Value *> args;
- args.push_back(op0);
- args.push_back(op1);
+ auto ty0 = op0->getType();
+ if (ty0->isHalfTy()
+#if LLVM_VERSION_MAJOR >= 11
+ || ty0->isBFloatTy()
+#endif
+ )
+ max_size = 16;
+ else if (ty0->isFloatTy())
+ max_size = 32;
+ else if (ty0->isDoubleTy())
+ max_size = 64;
+
+ if (max_size) {
+
+ Value *V0 = IRB.CreateBitCast(op0, IntegerType::get(C, max_size));
+ intTyOp0 = dyn_cast<IntegerType>(V0->getType());
+ Value *V1 = IRB.CreateBitCast(op1, IntegerType::get(C, max_size));
+ intTyOp1 = dyn_cast<IntegerType>(V1->getType());
+
+ if (intTyOp0 && intTyOp1) {
+
+ max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
+ ? intTyOp0->getBitWidth()
+ : intTyOp1->getBitWidth();
+ args.push_back(V0);
+ args.push_back(V1);
+
+ } else {
+
+ max_size = 0;
+
+ }
+
+ }
+
+ } else {
+
+ intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+ intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+
+ if (intTyOp0 && intTyOp1) {
+
+ max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
+ ? intTyOp0->getBitWidth()
+ : intTyOp1->getBitWidth();
+ args.push_back(op0);
+ args.push_back(op1);
+
+ }
+
+ }
+
+ if (max_size < 8 || max_size > 64 || !intTyOp0 || !intTyOp1) continue;
switch (max_size) {
diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc
index de8b97f0..da5cf7e9 100644
--- a/instrumentation/compare-transform-pass.so.cc
+++ b/instrumentation/compare-transform-pass.so.cc
@@ -68,7 +68,7 @@ class CompareTransform : public ModulePass {
const char *getPassName() const override {
#else
- StringRef getPassName() const override {
+ StringRef getPassName() const override {
#endif
return "transforms compare functions";
@@ -101,22 +101,31 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
IntegerType * Int64Ty = IntegerType::getInt64Ty(C);
#if LLVM_VERSION_MAJOR < 9
- Constant *
+ Function *tolowerFn;
#else
- FunctionCallee
+ FunctionCallee tolowerFn;
#endif
- c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty
+ {
+
+#if LLVM_VERSION_MAJOR < 9
+ Constant *
+#else
+ FunctionCallee
+#endif
+ c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty
#if LLVM_VERSION_MAJOR < 5
- ,
- NULL
+ ,
+ NULL
#endif
- );
+ );
#if LLVM_VERSION_MAJOR < 9
- Function *tolowerFn = cast<Function>(c);
+ tolowerFn = cast<Function>(c);
#else
- FunctionCallee tolowerFn = c;
+ tolowerFn = c;
#endif
+ }
+
/* iterate over all functions, bbs and instruction and add suitable calls to
* strcmp/memcmp/strncmp/strcasecmp/strncasecmp */
for (auto &F : M) {
@@ -234,7 +243,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (!HasStr2) {
- auto *Ptr = dyn_cast<ConstantExpr>(Str1P);
+ Ptr = dyn_cast<ConstantExpr>(Str1P);
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc
index 33a87719..b6d8c466 100644
--- a/instrumentation/split-compares-pass.so.cc
+++ b/instrumentation/split-compares-pass.so.cc
@@ -53,7 +53,7 @@ class SplitComparesTransform : public ModulePass {
public:
static char ID;
- SplitComparesTransform() : ModulePass(ID) {
+ SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) {
initInstrumentList();
@@ -555,6 +555,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
+ selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
@@ -735,6 +736,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
BasicBlock * signequal2_bb = signequal_bb;
switch (FcmpInst->getPredicate()) {
+ case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ:
icmp_exponent_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
@@ -816,6 +818,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
switch (FcmpInst->getPredicate()) {
+ case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ:
/* if the exponents are satifying the compare do a fraction cmp in
* middle_bb */
@@ -900,11 +903,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
/* compare the fractions of the operands */
Instruction *icmp_fraction_result;
- Instruction *icmp_fraction_result2;
BasicBlock * middle2_bb = middle_bb;
PHINode * PN2 = nullptr;
switch (FcmpInst->getPredicate()) {
+ case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ:
icmp_fraction_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
@@ -927,6 +930,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
case CmpInst::FCMP_OLT:
case CmpInst::FCMP_ULT: {
+ Instruction *icmp_fraction_result2;
+
middle2_bb = middle_bb->splitBasicBlock(
BasicBlock::iterator(middle_bb->getTerminator()));
@@ -980,6 +985,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
switch (FcmpInst->getPredicate()) {
+ case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ:
/* unequal signs cannot be equal values */
/* goto false branch */
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 43403430..9d6d7dba 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-d66c9e2654
+6ea7398ee3
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 6dac415b..0af489fe 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -26,9 +26,6 @@
#define AFL_MAIN
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
#include "config.h"
#include "types.h"
#include "debug.h"
@@ -903,8 +900,8 @@ static void usage(u8 *argv0) {
"Execution control settings:\n"
" -f file - input file read by the tested program (stdin)\n"
- " -t msec - timeout for each run (%d ms)\n"
- " -m megs - memory limit for child process (%d MB)\n"
+ " -t msec - timeout for each run (%u ms)\n"
+ " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
diff --git a/src/afl-cc.c b/src/afl-cc.c
index e6a6718e..f3dfd49f 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -120,8 +120,13 @@ char compiler_mode_string[7][12] = {
u8 *getthecwd() {
- static u8 fail[] = "";
- if (getcwd(cwd, sizeof(cwd)) == NULL) return fail;
+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
+
+ static u8 fail[] = "";
+ return fail;
+
+ }
+
return cwd;
}
@@ -581,6 +586,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
+#ifdef __ANDROID__
+ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+#else
if (have_instr_list) {
if (!be_quiet)
@@ -600,6 +608,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
+#endif
#else
#if LLVM_MAJOR >= 4
if (!be_quiet)
@@ -654,9 +663,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- u32 idx;
if (lto_mode && argc > 1) {
+ u32 idx;
for (idx = 1; idx < argc; idx++) {
if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
@@ -787,8 +796,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
-#if defined(USEMMAP) && !defined(__HAIKU__)
+#if defined(USEMMAP)
+ #if !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt";
+ #endif
#endif
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
@@ -822,6 +833,35 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"extern unsigned char *__afl_fuzz_ptr;"
"unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+
+ if (plusplus_mode) {
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
+ "extern \"C\" void __afl_coverage_discard();"
+ "extern \"C\" void __afl_coverage_skip();"
+ "extern \"C\" void __afl_coverage_on();"
+ "extern \"C\" void __afl_coverage_off();";
+
+ } else {
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
+ "void __afl_coverage_discard();"
+ "void __afl_coverage_skip();"
+ "void __afl_coverage_on();"
+ "void __afl_coverage_off();";
+
+ }
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = "
+ "1;";
+ cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()";
+ cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()";
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()";
+ cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()";
cc_params[cc_par_cnt++] =
"-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : "
"__afl_fuzz_alt_ptr)";
@@ -931,8 +971,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif
- #ifdef USEMMAP
+ #if defined(USEMMAP)
+ #if !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt";
+ #endif
#endif
}
@@ -996,6 +1038,10 @@ int main(int argc, char **argv, char **envp) {
#endif
+#ifdef __ANDROID__
+ have_llvm = 1;
+#endif
+
if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) {
have_gcc_plugin = 1;
@@ -1208,12 +1254,12 @@ int main(int argc, char **argv, char **envp) {
if (getenv("AFL_LLVM_INSTRUMENT")) {
- u8 *ptr = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;");
+ u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;");
- while (ptr) {
+ while (ptr2) {
- if (strncasecmp(ptr, "afl", strlen("afl")) == 0 ||
- strncasecmp(ptr, "classic", strlen("classic")) == 0) {
+ if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 ||
+ strncasecmp(ptr2, "classic", strlen("classic")) == 0) {
if (instrument_mode == INSTRUMENT_LTO) {
@@ -1229,8 +1275,8 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 ||
- strncasecmp(ptr, "pcguard", strlen("pcguard")) == 0) {
+ if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
+ strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD)
instrument_mode = INSTRUMENT_PCGUARD;
@@ -1241,8 +1287,8 @@ int main(int argc, char **argv, char **envp) {
}
// this is a hidden option
- if (strncasecmp(ptr, "llvmnative", strlen("llvmnative")) == 0 ||
- strncasecmp(ptr, "llvm-native", strlen("llvm-native")) == 0) {
+ if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 ||
+ strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE)
instrument_mode = INSTRUMENT_LLVMNATIVE;
@@ -1252,8 +1298,8 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr, "cfg", strlen("cfg")) == 0 ||
- strncasecmp(ptr, "instrim", strlen("instrim")) == 0) {
+ if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
+ strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
if (instrument_mode == INSTRUMENT_LTO) {
@@ -1269,7 +1315,7 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr, "lto", strlen("lto")) == 0) {
+ if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) {
lto_mode = 1;
if (!instrument_mode || instrument_mode == INSTRUMENT_LTO)
@@ -1280,7 +1326,7 @@ int main(int argc, char **argv, char **envp) {
}
- if (strcasecmp(ptr, "gcc") == 0) {
+ if (strcasecmp(ptr2, "gcc") == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_GCC)
instrument_mode = INSTRUMENT_GCC;
@@ -1291,7 +1337,7 @@ int main(int argc, char **argv, char **envp) {
}
- if (strcasecmp(ptr, "clang") == 0) {
+ if (strcasecmp(ptr2, "clang") == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG)
instrument_mode = INSTRUMENT_CLANG;
@@ -1302,29 +1348,29 @@ int main(int argc, char **argv, char **envp) {
}
- if (strncasecmp(ptr, "ctx", strlen("ctx")) == 0) {
+ if (strncasecmp(ptr2, "ctx", strlen("ctx")) == 0) {
instrument_opt_mode |= INSTRUMENT_OPT_CTX;
setenv("AFL_LLVM_CTX", "1", 1);
}
- if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) {
+ if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) {
- ptr += strlen("ngram");
- while (*ptr && (*ptr < '0' || *ptr > '9'))
- ptr++;
+ ptr2 += strlen("ngram");
+ while (*ptr2 && (*ptr2 < '0' || *ptr2 > '9'))
+ ptr2++;
- if (!*ptr) {
+ if (!*ptr2) {
- if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL)
+ if ((ptr2 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL)
FATAL(
"you must set the NGRAM size with (e.g. for value 2) "
"AFL_LLVM_INSTRUMENT=ngram-2");
}
- ngram_size = atoi(ptr);
+ ngram_size = atoi(ptr2);
if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX)
FATAL(
"NGRAM instrumentation option must be between 2 and "
@@ -1332,12 +1378,12 @@ int main(int argc, char **argv, char **envp) {
"(%u)",
NGRAM_SIZE_MAX);
instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM);
- ptr = alloc_printf("%u", ngram_size);
- setenv("AFL_LLVM_NGRAM_SIZE", ptr, 1);
+ ptr2 = alloc_printf("%u", ngram_size);
+ setenv("AFL_LLVM_NGRAM_SIZE", ptr2, 1);
}
- ptr = strtok(NULL, ":,;");
+ ptr2 = strtok(NULL, ":,;");
}
@@ -1448,20 +1494,28 @@ int main(int argc, char **argv, char **envp) {
" The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n");
+#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
+ #define NATIVE_MSG \
+ " NATIVE: use llvm's native PCGUARD instrumentation (less " \
+ "performant)\n"
+#else
+ #define NATIVE_MSG ""
+#endif
+
SAYF(
"Sub-Modes: (set via env AFL_LLVM_INSTRUMENT, afl-cc selects the best "
"available)\n"
" PCGUARD: Dominator tree instrumentation (best!) (README.llvm.md)\n"
-#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
- " NATIVE: use llvm's native PCGUARD instrumentation (less "
- "performant)\n"
-#endif
+
+ NATIVE_MSG
+
" CLASSIC: decision target instrumentation (README.llvm.md)\n"
" CTX: CLASSIC + callee context (instrumentation/README.ctx.md)\n"
" NGRAM-x: CLASSIC + previous path "
"((instrumentation/README.ngram.md)\n"
" INSTRIM: Dominator tree (for LLVM <= 6.0) "
"(instrumentation/README.instrim.md)\n\n");
+#undef NATIVE_MSG
SAYF(
"Features: (see documentation links)\n"
@@ -1595,12 +1649,17 @@ int main(int argc, char **argv, char **envp) {
if (have_lto)
SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO);
if (have_llvm)
- SAYF("afl-cc LLVM version %d with the the binary path \"%s\".\n",
- LLVM_MAJOR, LLVM_BINDIR);
+ SAYF("afl-cc LLVM version %d using binary path \"%s\".\n", LLVM_MAJOR,
+ LLVM_BINDIR);
#endif
-#ifdef USEMMAP
+#if defined(USEMMAP)
+ #if !defined(__HAIKU__)
+ cc_params[cc_par_cnt++] = "-lrt";
SAYF("Compiled with shm_open support (adds -lrt when linking).\n");
+ #else
+ SAYF("Compiled with shm_open support.\n");
+ #endif
#else
SAYF("Compiled with shmat support.\n");
#endif
@@ -1625,7 +1684,7 @@ int main(int argc, char **argv, char **envp) {
if (!instrument_mode) {
instrument_mode = INSTRUMENT_CFG;
- ptr = instrument_mode_string[instrument_mode];
+ // ptr = instrument_mode_string[instrument_mode];
}
@@ -1734,15 +1793,6 @@ int main(int argc, char **argv, char **envp) {
}
- if (!be_quiet && !lto_mode &&
- ((ptr2 = getenv("AFL_MAP_SIZE")) || (ptr2 = getenv("AFL_MAPSIZE")))) {
-
- u32 map_size = atoi(ptr2);
- if (map_size != MAP_SIZE)
- WARNF("AFL_MAP_SIZE is not supported by afl-clang-fast");
-
- }
-
if (debug) {
DEBUGF("cd '%s';", getthecwd());
@@ -1765,11 +1815,8 @@ int main(int argc, char **argv, char **envp) {
if (!be_quiet && cmplog_mode)
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
-#ifdef __ANDROID__
- ptr = find_object("afl-compiler-rt.so", argv[0]);
-#else
+#ifndef __ANDROID__
ptr = find_object("afl-compiler-rt.o", argv[0]);
-#endif
if (!ptr) {
@@ -1782,6 +1829,7 @@ int main(int argc, char **argv, char **envp) {
if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
ck_free(ptr);
+#endif
edit_params(argc, argv, envp);
diff --git a/src/afl-common.c b/src/afl-common.c
index 1928663d..cf996548 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -424,6 +424,40 @@ u8 *find_binary(u8 *fname) {
}
+/* Parses the kill signal environment variable, FATALs on error.
+ If the env is not set, sets the env to default_signal for the signal handlers
+ and returns the default_signal. */
+int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
+
+ if (afl_kill_signal_env && afl_kill_signal_env[0]) {
+
+ char *endptr;
+ u8 signal_code;
+ signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
+ /* Did we manage to parse the full string? */
+ if (*endptr != '\0' || endptr == (char *)afl_kill_signal_env) {
+
+ FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
+ afl_kill_signal_env);
+
+ }
+
+ return signal_code;
+
+ } else {
+
+ char *sigstr = alloc_printf("%d", default_signal);
+ if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
+
+ /* Set the env for signal handler */
+ setenv("AFL_KILL_SIGNAL", sigstr, 1);
+ free(sigstr);
+ return default_signal;
+
+ }
+
+}
+
void check_environment_vars(char **envp) {
if (be_quiet) { return; }
@@ -696,16 +730,16 @@ u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
- u64 delta;
- s32 t_d, t_h, t_m, t_s;
- u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
-
if (!event_ms) {
snprintf(buf, len, "none seen yet");
} else {
+ u64 delta;
+ s32 t_d, t_h, t_m, t_s;
+ u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
delta = cur_ms - event_ms;
t_d = delta / 1000 / 60 / 60 / 24;
@@ -858,16 +892,16 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val) {
u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
- u64 delta;
- s32 t_d, t_h, t_m, t_s;
- u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
-
if (!event_ms) {
sprintf(buf, "none seen yet");
} else {
+ u64 delta;
+ s32 t_d, t_h, t_m, t_s;
+ u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
+
delta = cur_ms - event_ms;
t_d = delta / 1000 / 60 / 60 / 24;
@@ -893,14 +927,14 @@ u32 get_map_size(void) {
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
map_size = atoi(ptr);
- if (map_size < 8 || map_size > (1 << 29)) {
+ if (!map_size || map_size > (1 << 29)) {
- FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8,
- 1 << 29);
+ FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 32U,
+ 1U << 29);
}
- if (map_size % 8) { map_size = (((map_size >> 3) + 1) << 3); }
+ if (map_size % 32) { map_size = (((map_size >> 5) + 1) << 5); }
}
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 90fa55e9..39f044f2 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -84,6 +84,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL;
+ fsrv->kill_signal = SIGKILL;
/* exec related stuff */
fsrv->child_pid = -1;
@@ -95,7 +96,6 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->uses_asan = false;
fsrv->init_child_func = fsrv_exec_child;
-
list_append(&fsrv_list, fsrv);
}
@@ -116,6 +116,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->no_unlink = from->no_unlink;
fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
fsrv_to->crash_exitcode = from->crash_exitcode;
+ fsrv_to->kill_signal = from->kill_signal;
// These are forkserver specific.
fsrv_to->out_dir_fd = -1;
@@ -213,7 +214,7 @@ restart_select:
static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
unsigned char tmp[4] = {0, 0, 0, 0};
- pid_t child_pid = -1;
+ pid_t child_pid;
if (!be_quiet) { ACTF("Using Fauxserver:"); }
@@ -559,12 +560,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!time_ms) {
- kill(fsrv->fsrv_pid, SIGKILL);
+ kill(fsrv->fsrv_pid, fsrv->kill_signal);
} else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1;
- kill(fsrv->fsrv_pid, SIGKILL);
+ kill(fsrv->fsrv_pid, fsrv->kill_signal);
} else {
@@ -807,6 +808,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"before receiving any input\n"
" from the fuzzer! There are several probable explanations:\n\n"
+ " - The target binary requires a large map and crashes before "
+ "reporting.\n"
+ " Set a high value (e.g. AFL_MAP_SIZE=1024000) or use "
+ "AFL_DEBUG=1 to see the\n"
+ " message from the target binary\n\n"
+
" - The binary is just buggy and explodes entirely on its own. "
"If so, you\n"
" need to fix the underlying problem or find a better "
@@ -828,6 +835,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"before receiving any input\n"
" from the fuzzer! There are several probable explanations:\n\n"
+ " - The target binary requires a large map and crashes before "
+ "reporting.\n"
+ " Set a high value (e.g. AFL_MAP_SIZE=1024000) or use "
+ "AFL_DEBUG=1 to see the\n"
+ " message from the target binary\n\n"
+
" - The current memory limit (%s) is too restrictive, causing "
"the\n"
" target to hit an OOM condition in the dynamic linker. Try "
@@ -944,10 +957,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
- if (fsrv->child_pid > 0) { kill(fsrv->child_pid, SIGKILL); }
+ if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
if (fsrv->fsrv_pid > 0) {
- kill(fsrv->fsrv_pid, SIGKILL);
+ kill(fsrv->fsrv_pid, fsrv->kill_signal);
if (waitpid(fsrv->fsrv_pid, NULL, 0) <= 0) { WARNF("error waitpid\n"); }
}
@@ -971,10 +984,10 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
hash64(fsrv->shmem_fuzz, *fsrv->shmem_fuzz_len, 0xa5b35705),
*fsrv->shmem_fuzz_len);
fprintf(stderr, "SHM :");
- for (int i = 0; i < *fsrv->shmem_fuzz_len; i++)
+ for (u32 i = 0; i < *fsrv->shmem_fuzz_len; i++)
fprintf(stderr, "%02x", fsrv->shmem_fuzz[i]);
fprintf(stderr, "\nORIG:");
- for (int i = 0; i < *fsrv->shmem_fuzz_len; i++)
+ for (u32 i = 0; i < *fsrv->shmem_fuzz_len; i++)
fprintf(stderr, "%02x", buf[i]);
fprintf(stderr, "\n");
@@ -1091,7 +1104,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */
- kill(fsrv->child_pid, SIGKILL);
+ kill(fsrv->child_pid, fsrv->kill_signal);
fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }
@@ -1104,7 +1117,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
"Unable to communicate with fork server. Some possible reasons:\n\n"
" - You've run out of memory. Use -m to increase the the memory "
"limit\n"
- " to something higher than %lld.\n"
+ " to something higher than %llu.\n"
" - The binary or one of the libraries it uses manages to "
"create\n"
" threads before the forkserver initializes.\n"
@@ -1137,36 +1150,44 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* Report outcome to caller. */
- if (WIFSIGNALED(fsrv->child_status) && !*stop_soon_p) {
+ /* Was the run unsuccessful? */
+ if (unlikely(*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG)) {
- fsrv->last_kill_signal = WTERMSIG(fsrv->child_status);
+ return FSRV_RUN_ERROR;
- if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) {
-
- return FSRV_RUN_TMOUT;
+ }
- }
+ /* Did we timeout? */
+ if (unlikely(fsrv->last_run_timed_out)) {
- return FSRV_RUN_CRASH;
+ fsrv->last_kill_signal = fsrv->kill_signal;
+ return FSRV_RUN_TMOUT;
}
- /* MSAN in uses_asan mode uses a special exit code as it doesn't support
- abort_on_error.
- On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */
-
- if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
- (fsrv->uses_crash_exitcode &&
- WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) {
-
- fsrv->last_kill_signal = 0;
+ /* Did we crash?
+ In a normal case, (abort) WIFSIGNALED(child_status) will be set.
+ MSAN in uses_asan mode uses a special exit code as it doesn't support
+ abort_on_error. On top, a user may specify a custom AFL_CRASH_EXITCODE.
+ Handle all three cases here. */
+
+ if (unlikely(
+ /* A normal crash/abort */
+ (WIFSIGNALED(fsrv->child_status)) ||
+ /* special handling for msan */
+ (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+ /* the custom crash_exitcode was returned by the target */
+ (fsrv->uses_crash_exitcode &&
+ WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
+
+ /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
+ fsrv->last_kill_signal =
+ WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
return FSRV_RUN_CRASH;
}
- // Fauxserver should handle this now.
- if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
-
+ /* success :) */
return FSRV_RUN_OK;
}
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 62a8211c..586f3990 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -703,7 +703,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (!classified) {
classify_counts(&afl->fsrv);
- classified = 1;
}
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 171cce96..a3583651 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -266,7 +266,7 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
if (afl->extras_cnt > afl->max_det_extras) {
- WARNF("More than %d tokens - will use them probabilistically.",
+ WARNF("More than %u tokens - will use them probabilistically.",
afl->max_det_extras);
}
@@ -431,7 +431,6 @@ void dedup_extras(afl_state_t *afl) {
/* Adds a new extra / dict entry. */
void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
- u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
u32 i, found = 0;
for (i = 0; i < afl->extras_cnt; i++) {
@@ -451,6 +450,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
if (len > MAX_DICT_FILE) {
+ u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
WARNF("Extra '%.*s' is too big (%s, limit is %s), skipping file!", (int)len,
mem, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
@@ -481,7 +481,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
if (afl->extras_cnt == afl->max_det_extras + 1) {
- WARNF("More than %d tokens - will use them probabilistically.",
+ WARNF("More than %u tokens - will use them probabilistically.",
afl->max_det_extras);
}
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 0c85458e..80df6d08 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -141,7 +141,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
mutator->name = fn;
- mutator->name_short = strrchr(fn, '/') + 1;
+ if (memchr(fn, '/', strlen(fn)))
+ mutator->name_short = strrchr(fn, '/') + 1;
+ else
+ mutator->name_short = strdup(fn);
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
@@ -316,16 +319,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
/* Initialize trimming in the custom mutator */
afl->stage_cur = 0;
- afl->stage_max = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len);
- if (unlikely(afl->stage_max) < 0) {
+ s32 retval = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len);
+ if (unlikely(retval) < 0) {
- FATAL("custom_init_trim error ret: %d", afl->stage_max);
+ FATAL("custom_init_trim error ret: %d", retval);
+
+ } else {
+
+ afl->stage_max = retval;
}
if (afl->not_on_tty && afl->debug) {
- SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
+ SAYF("[Custom Trimming] START: Max %u iterations, %u bytes", afl->stage_max,
q->len);
}
@@ -343,7 +350,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (unlikely(!retbuf)) {
- FATAL("custom_trim failed (ret %zd)", retlen);
+ FATAL("custom_trim failed (ret %zu)", retlen);
} else if (unlikely(retlen > orig_len)) {
@@ -409,7 +416,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (afl->not_on_tty && afl->debug) {
- SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
+ SAYF("[Custom Trimming] SUCCESS: %u/%u iterations (now at %u bytes)",
afl->stage_cur, afl->stage_max, q->len);
}
@@ -417,16 +424,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
} else {
/* Tell the custom mutator that the trimming was unsuccessful */
- afl->stage_cur = mutator->afl_custom_post_trim(mutator->data, 0);
- if (unlikely(afl->stage_cur < 0)) {
+ s32 retval2 = mutator->afl_custom_post_trim(mutator->data, 0);
+ if (unlikely(retval2 < 0)) {
+
+ FATAL("Error ret in custom_post_trim: %d", retval2);
+
+ } else {
- FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
+ afl->stage_cur = retval2;
}
if (afl->not_on_tty && afl->debug) {
- SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
+ SAYF("[Custom Trimming] FAILURE: %u/%u iterations", afl->stage_cur,
afl->stage_max);
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index e6fa6064..f9509e86 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -368,7 +368,7 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
u8 fuzz_one_original(afl_state_t *afl) {
- s32 len, temp_len;
+ u32 len, temp_len;
u32 j;
u32 i;
u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
@@ -545,7 +545,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
else
orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
- if (unlikely(perf_score <= 0)) { goto abandon_entry; }
+ if (unlikely(perf_score == 0)) { goto abandon_entry; }
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
@@ -902,7 +902,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
orig_hit_cnt = new_hit_cnt;
- for (i = 0; (s32)i < len - 1; ++i) {
+ for (i = 0; i < len - 1; ++i) {
/* Let's consult the effector map... */
@@ -945,7 +945,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
orig_hit_cnt = new_hit_cnt;
- for (i = 0; (s32)i < len - 3; ++i) {
+ for (i = 0; i < len - 3; ++i) {
/* Let's consult the effector map... */
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
@@ -1405,7 +1405,7 @@ skip_arith:
orig_hit_cnt = new_hit_cnt;
- for (i = 0; (s32)i < len - 1; ++i) {
+ for (i = 0; i < len - 1; ++i) {
u16 orig = *(u16 *)(out_buf + i);
@@ -1493,7 +1493,7 @@ skip_arith:
orig_hit_cnt = new_hit_cnt;
- for (i = 0; (s32)i < len - 3; i++) {
+ for (i = 0; i < len - 3; i++) {
u32 orig = *(u32 *)(out_buf + i);
@@ -1850,7 +1850,7 @@ custom_mutator_stage:
if (unlikely(!mutated_buf)) {
- FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
+ FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size);
}
@@ -2026,7 +2026,7 @@ havoc_stage:
el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
if (unlikely(!custom_havoc_buf)) {
- FATAL("Error in custom_havoc (return %zd)", new_len);
+ FATAL("Error in custom_havoc (return %zu)", new_len);
}
@@ -2458,7 +2458,7 @@ havoc_stage:
u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len;
- if ((s32)extra_len > temp_len) { break; }
+ if (extra_len > temp_len) { break; }
u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
@@ -2476,7 +2476,7 @@ havoc_stage:
u32 use_extra = rand_below(afl, afl->extras_cnt);
u32 extra_len = afl->extras[use_extra].len;
- if ((s32)extra_len > temp_len) { break; }
+ if (extra_len > temp_len) { break; }
u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
@@ -2577,7 +2577,7 @@ havoc_stage:
u32 copy_from, copy_to, copy_len;
copy_len = choose_block_len(afl, new_len - 1);
- if ((s32)copy_len > temp_len) copy_len = temp_len;
+ if (copy_len > temp_len) copy_len = temp_len;
copy_from = rand_below(afl, new_len - copy_len + 1);
copy_to = rand_below(afl, temp_len - copy_len + 1);
@@ -2952,7 +2952,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
else
orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
- if (unlikely(perf_score <= 0)) { goto abandon_entry; }
+ if (unlikely(perf_score == 0)) { goto abandon_entry; }
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 9a0d199e..66938635 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -43,7 +43,8 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
double compute_weight(afl_state_t *afl, struct queue_entry *q,
- double avg_exec_us, double avg_bitmap_size) {
+ double avg_exec_us, double avg_bitmap_size,
+ double avg_top_size) {
double weight = 1.0;
@@ -54,9 +55,9 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
}
- weight *= avg_exec_us / q->exec_us;
+ if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
weight *= (log(q->bitmap_size) / avg_bitmap_size);
-
+ weight *= (1 + (q->tc_ref / avg_top_size));
if (unlikely(q->favored)) weight *= 5;
return weight;
@@ -91,6 +92,7 @@ void create_alias_table(afl_state_t *afl) {
double avg_exec_us = 0.0;
double avg_bitmap_size = 0.0;
+ double avg_top_size = 0.0;
u32 active = 0;
for (i = 0; i < n; i++) {
@@ -102,6 +104,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us += q->exec_us;
avg_bitmap_size += log(q->bitmap_size);
+ avg_top_size += q->tc_ref;
++active;
}
@@ -110,6 +113,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us /= active;
avg_bitmap_size /= active;
+ avg_top_size /= active;
for (i = 0; i < n; i++) {
@@ -117,7 +121,8 @@ void create_alias_table(afl_state_t *afl) {
if (likely(!q->disabled)) {
- q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size);
+ q->weight =
+ compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
q->perf_score = calculate_score(afl, q);
sum += q->weight;
@@ -489,11 +494,12 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
void destroy_queue(afl_state_t *afl) {
- struct queue_entry *q;
- u32 i;
+ u32 i;
for (i = 0; i < afl->queued_paths; i++) {
+ struct queue_entry *q;
+
q = afl->queue_buf[i];
ck_free(q->fname);
ck_free(q->trace_mini);
@@ -996,7 +1002,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
if (unlikely(!q->testcase_buf)) {
- PFATAL("Unable to malloc '%s' with len %d", q->fname, len);
+ PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
}
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 37d66aef..28585afe 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -99,12 +99,12 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
}
-static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) {
+static void xor_replace(u8 *buf, u32 len) {
u32 i;
for (i = 0; i < len; ++i) {
- buf[i] = rand_below(afl, 256);
+ buf[i] ^= 0xff;
}
@@ -115,8 +115,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
struct range *ranges = add_range(NULL, 0, len);
u8 * backup = ck_alloc_nozero(len);
- u8 needs_write = 0;
-
u64 orig_hit_cnt, new_hit_cnt;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@@ -136,7 +134,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
/* Range not empty */
memcpy(backup, buf + rng->start, s);
- rand_replace(afl, buf + rng->start, s);
+ xor_replace(buf + rng->start, s);
u64 cksum;
u64 start_us = get_cur_time_us();
@@ -158,10 +156,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
ranges = add_range(ranges, rng->start + s / 2 + 1, rng->end);
memcpy(buf + rng->start, backup, s);
- } else {
-
- needs_write = 1;
-
}
}
@@ -191,32 +185,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
}
- // save the input with the high entropy
-
- if (needs_write) {
-
- s32 fd;
-
- if (afl->no_unlink) {
-
- fd = open(afl->queue_cur->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-
- } else {
-
- unlink(afl->queue_cur->fname); /* ignore errors */
- fd = open(afl->queue_cur->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
-
- }
-
- if (fd < 0) { PFATAL("Unable to create '%s'", afl->queue_cur->fname); }
-
- ck_write(fd, buf, len, afl->queue_cur->fname);
- afl->queue_cur->len = len; // no-op, just to be 100% safe
-
- close(fd);
-
- }
-
return 0;
checksum_fail:
@@ -232,8 +200,6 @@ checksum_fail:
}
- // TODO: clang notices a _potential_ leak of mem pointed to by rng
-
return 1;
}
@@ -479,6 +445,10 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u32 k;
u8 cons_ff = 0, cons_0 = 0;
+
+ if (shape > sizeof(v))
+ FATAL("shape is greater than %zu, please report!", sizeof(v));
+
for (k = 0; k < shape; ++k) {
if (b[k] == 0) {
@@ -487,7 +457,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
} else if (b[k] == 0xff) {
- ++cons_0;
+ ++cons_ff;
} else {
@@ -701,12 +671,12 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
u8 status = 0;
// opt not in the paper
- u32 fails = 0;
- u8 found_one = 0;
+ // u32 fails = 0;
+ u8 found_one = 0;
for (i = 0; i < loggeds; ++i) {
- fails = 0;
+ u32 fails = 0;
struct cmpfn_operands *o =
&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i];
@@ -802,13 +772,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
u64 exec_cksum) {
u8 r = 1;
- if (afl->orig_cmp_map == NULL) {
+ if (unlikely(!afl->orig_cmp_map)) {
afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
}
- if (afl->pass_stats == NULL) {
+ if (unlikely(!afl->pass_stats)) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
@@ -888,7 +858,7 @@ exit_its:
afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs;
- memcpy(orig_buf, buf, len);
+ memcpy(buf, orig_buf, len);
return r;
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 339fb9c3..17c305ed 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -230,10 +230,10 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
hash64(afl->fsrv.shmem_fuzz, *afl->fsrv.shmem_fuzz_len, 0xa5b35705),
*afl->fsrv.shmem_fuzz_len);
fprintf(stderr, "SHM :");
- for (int i = 0; i < *afl->fsrv.shmem_fuzz_len; i++)
+ for (u32 i = 0; i < *afl->fsrv.shmem_fuzz_len; i++)
fprintf(stderr, "%02x", afl->fsrv.shmem_fuzz[i]);
fprintf(stderr, "\nORIG:");
- for (int i = 0; i < *afl->fsrv.shmem_fuzz_len; i++)
+ for (u32 i = 0; i < *afl->fsrv.shmem_fuzz_len; i++)
fprintf(stderr, "%02x", (u8)((u8 *)mem)[i]);
fprintf(stderr, "\n");
@@ -296,11 +296,11 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 handicap, u8 from_queue) {
+ if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
+
u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
first_run = (q->exec_cksum == 0);
-
- u64 start_us, stop_us;
-
+ u64 start_us, stop_us, diff_us;
s32 old_sc = afl->stage_cur, old_sm = afl->stage_max;
u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name;
@@ -422,15 +422,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
- stop_us = get_cur_time_us();
+ if (unlikely(afl->fixed_seed)) {
+
+ diff_us = (u64)(afl->fsrv.exec_tmout - 1) * (u64)afl->stage_max;
+
+ } else {
+
+ stop_us = get_cur_time_us();
+ diff_us = stop_us - start_us;
+ if (unlikely(!diff_us)) { ++diff_us; }
- afl->total_cal_us += stop_us - start_us;
+ }
+
+ afl->total_cal_us += diff_us;
afl->total_cal_cycles += afl->stage_max;
/* OK, let's collect some stats about the performance of this test case.
This is used for fuzzing air time calculations in calculate_score(). */
- q->exec_us = (stop_us - start_us) / afl->stage_max;
+ if (unlikely(!afl->stage_max)) {
+
+ // Pretty sure this cannot happen, yet scan-build complains.
+ FATAL("BUG: stage_max should not be 0 here! Please report this condition.");
+
+ }
+
+ q->exec_us = diff_us / afl->stage_max;
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
q->handicap = handicap;
q->cal_failed = 0;
@@ -682,7 +699,7 @@ void sync_fuzzers(afl_state_t *afl) {
// same time. If so, the first temporary main node running again will demote
// themselves so this is not an issue
- u8 path[PATH_MAX];
+ // u8 path2[PATH_MAX];
afl->is_main_node = 1;
sprintf(path, "%s/is_main_node", afl->out_dir);
int fd = open(path, O_CREAT | O_RDWR, 0644);
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 34456c0d..60c9684c 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -418,6 +418,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
(u8 *)get_afl_env(afl_environment_variables[i]);
#endif
+ } else if (!strncmp(env, "AFL_KILL_SIGNAL",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_kill_signal =
+ (u8 *)get_afl_env(afl_environment_variables[i]);
+
}
} else {
@@ -524,8 +531,8 @@ void afl_states_stop(void) {
LIST_FOREACH(&afl_states, afl_state_t, {
- if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, SIGKILL);
- if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, SIGKILL);
+ if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, el->fsrv.kill_signal);
+ if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, el->fsrv.kill_signal);
});
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index cb0d3dcd..e67bace9 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -31,8 +31,7 @@
void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
- char *val;
- u8 fn[PATH_MAX];
+ u8 fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
FILE *f = create_ffile(fn);
u32 i;
@@ -44,6 +43,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
for (i = 0; i < s_afl_env; ++i) {
+ char *val;
if ((val = getenv(afl_environment_variables[i])) != NULL) {
fprintf(f, "%s=%s\n", afl_environment_variables[i], val);
@@ -58,7 +58,11 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
for (i = 0; i < argc; ++i) {
if (i) fprintf(f, " ");
+#ifdef __ANDROID__
+ if (memchr(argv[i], '\'', sizeof(argv[i]))) {
+#else
if (index(argv[i], '\'')) {
+#endif
fprintf(f, "'");
for (j = 0; j < strlen(argv[i]); j++)
@@ -120,8 +124,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
cur_time - afl->last_avg_exec_update >= 60000))) {
afl->last_avg_execs_saved =
- (float)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) /
- (float)(cur_time - afl->last_avg_exec_update);
+ (double)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) /
+ (double)(cur_time - afl->last_avg_exec_update);
afl->last_avg_execs = afl->fsrv.total_execs;
afl->last_avg_exec_update = cur_time;
@@ -228,7 +232,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
if (afl->virgin_bits[i] != 0xff) {
- fprintf(f, " %d[%02x]", i, afl->virgin_bits[i]);
+ fprintf(f, " %u[%02x]", i, afl->virgin_bits[i]);
}
@@ -238,7 +242,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
fprintf(f, "var_bytes :");
for (i = 0; i < afl->fsrv.map_size; i++) {
- if (afl->var_bytes[i]) { fprintf(f, " %d", i); }
+ if (afl->var_bytes[i]) { fprintf(f, " %u", i); }
}
@@ -1163,7 +1167,7 @@ void show_init_stats(afl_state_t *afl) {
} else {
- ACTF("-t option specified. We'll use an exec timeout of %d ms.",
+ ACTF("-t option specified. We'll use an exec timeout of %u ms.",
afl->fsrv.exec_tmout);
}
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 2af374f2..7facf261 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -76,8 +76,17 @@ static void at_exit() {
}
- if (pid1 > 0) { kill(pid1, SIGKILL); }
- if (pid2 > 0) { kill(pid2, SIGKILL); }
+ int kill_signal = SIGKILL;
+
+ /* AFL_KILL_SIGNAL should already be a valid int at this point */
+ if (getenv("AFL_KILL_SIGNAL")) {
+
+ kill_signal = atoi(getenv("AFL_KILL_SIGNAL"));
+
+ }
+
+ if (pid1 > 0) { kill(pid1, kill_signal); }
+ if (pid2 > 0) { kill(pid2, kill_signal); }
}
@@ -94,13 +103,13 @@ static void usage(u8 *argv0, int more_help) {
"Execution control settings:\n"
" -p schedule - power schedules compute a seed's performance score:\n"
- " <explore(default), rare, exploit, seek, mmopt, coe, "
- "fast,\n"
+ " <fast(default), rare, exploit, seek, mmopt, coe, "
+ "explore,\n"
" lin, quad> -- see docs/power_schedules.md\n"
" -f file - location read by the fuzzed program (default: stdin "
"or @@)\n"
- " -t msec - timeout for each run (auto-scaled, 50-%d ms)\n"
- " -m megs - memory limit for child process (%d MB, 0 = no limit)\n"
+ " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n"
+ " -m megs - memory limit for child process (%u MB, 0 = no limit)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
@@ -185,10 +194,11 @@ static void usage(u8 *argv0, int more_help) {
"AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n"
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
- "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
+ "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
@@ -299,7 +309,8 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/;
u64 prev_queued = 0;
- u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = MAP_SIZE;
+ u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0,
+ map_size = get_map_size();
u8 *extras_dir[4];
u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
extras_dir_cnt = 0 /*, have_p = 0*/;
@@ -326,7 +337,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
- map_size = get_map_size();
afl_state_init(afl, map_size);
afl->debug = debug;
afl_fsrv_init(&afl->fsrv);
@@ -575,7 +585,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
- if (sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
+ if (!optarg || sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
optarg[0] == '-') {
FATAL("Bad syntax used for -t");
@@ -757,7 +767,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'V': {
afl->most_time_key = 1;
- if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') {
+ if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') {
FATAL("Bad syntax used for -V");
@@ -768,7 +778,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'E': {
afl->most_execs_key = 1;
- if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') {
+ if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') {
FATAL("Bad syntax used for -E");
@@ -976,6 +986,9 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
+ afl->fsrv.kill_signal =
+ parse_afl_kill_signal_env(afl->afl_env.afl_kill_signal, SIGKILL);
+
setup_signal_handlers();
check_asan_opts(afl);
@@ -1534,7 +1547,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->pending_not_fuzzed) {
- FATAL("We need at least on valid input seed that does not crash!");
+ FATAL("We need at least one valid input seed that does not crash!");
}
@@ -1767,15 +1780,27 @@ int main(int argc, char **argv_orig, char **envp) {
} while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
- if (!afl->stop_soon && afl->sync_id) {
+ if (likely(!afl->stop_soon && afl->sync_id)) {
+
+ if (likely(afl->skip_deterministic)) {
- if (unlikely(afl->is_main_node)) {
+ if (unlikely(afl->is_main_node)) {
- if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { sync_fuzzers(afl); }
+ if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
+
+ sync_fuzzers(afl);
+
+ }
+
+ } else {
+
+ if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+
+ }
} else {
- if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+ sync_fuzzers(afl);
}
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index 1aea3e40..ac002a93 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -35,9 +35,6 @@
#define _GNU_SOURCE
#endif
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index fccdb1a5..0671d1c4 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -187,7 +187,7 @@ static void edit_params(int argc, char **argv) {
if (debug)
DEBUGF(
- "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
+ "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s "
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
passthrough ? "true" : "false", instrim, gold_pos,
gold_present ? "true" : "false", inst_present ? "true" : "false",
@@ -252,11 +252,10 @@ static void edit_params(int argc, char **argv) {
int main(int argc, char **argv) {
- s32 pid, i, status;
- u8 * ptr;
+ s32 pid, i, status;
char thecwd[PATH_MAX];
- if ((ptr = getenv("AFL_LD_CALLER")) != NULL) {
+ if (getenv("AFL_LD_CALLER") != NULL) {
FATAL("ld loop detected! Set AFL_REAL_LD!\n");
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 355b2dc3..6d95fc1d 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -31,9 +31,6 @@
#define AFL_MAIN
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
#include "config.h"
#include "types.h"
#include "debug.h"
@@ -662,7 +659,7 @@ static void usage(u8 *argv0) {
"Execution control settings:\n"
" -t msec - timeout for each run (none)\n"
- " -m megs - memory limit for child process (%d MB)\n"
+ " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use Unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
@@ -693,12 +690,13 @@ static void usage(u8 *argv0) {
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
"crash\n"
"AFL_DEBUG: enable extra developer output\n"
- "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
- "size\n"
- " the target was compiled for\n"
- "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
"startup (in milliseconds)\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, "
+ "etc. (default: SIGKILL)\n"
+ "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
+ "size the target was compiled for\n"
+ "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_QUIET: do not print extra informational output\n",
argv0, MEM_LIMIT, doc_path);
@@ -1014,9 +1012,9 @@ int main(int argc, char **argv_orig, char **envp) {
DIR * dir_in, *dir_out = NULL;
struct dirent *dir_ent;
- int done = 0;
- u8 infile[PATH_MAX], outfile[PATH_MAX];
- u8 wait_for_gdb = 0;
+ // int done = 0;
+ u8 infile[PATH_MAX], outfile[PATH_MAX];
+ u8 wait_for_gdb = 0;
#if !defined(DT_REG)
struct stat statbuf;
#endif
@@ -1090,11 +1088,11 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) {
- int i = optind;
+ int j = optind;
DEBUGF("%s:", fsrv->target_path);
- while (argv[i] != NULL) {
+ while (argv[j] != NULL) {
- SAYF(" \"%s\"", argv[i++]);
+ SAYF(" \"%s\"", argv[j++]);
}
@@ -1115,6 +1113,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ fsrv->kill_signal =
+ parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
+
if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
@@ -1143,7 +1144,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
- while (done == 0 && (dir_ent = readdir(dir_in))) {
+ while ((dir_ent = readdir(dir_in))) {
if (dir_ent->d_name[0] == '.') {
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index ed928c7c..5fd60cd2 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -29,10 +29,6 @@
#define AFL_MAIN
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
-
#include "config.h"
#include "types.h"
#include "debug.h"
@@ -835,8 +831,8 @@ static void usage(u8 *argv0) {
"Execution control settings:\n"
" -f file - input file read by the tested program (stdin)\n"
- " -t msec - timeout for each run (%d ms)\n"
- " -m megs - memory limit for child process (%d MB)\n"
+ " -t msec - timeout for each run (%u ms)\n"
+ " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
@@ -855,6 +851,7 @@ static void usage(u8 *argv0) {
"Environment variables used:\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
@@ -1134,6 +1131,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ fsrv->kill_signal =
+ parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
+
if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
diff --git a/test/test-basic.sh b/test/test-basic.sh
index 79f90ea0..8296b6cc 100755
--- a/test/test-basic.sh
+++ b/test/test-basic.sh
@@ -106,7 +106,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
;;
esac
} else {
- $ECHO "$GRAY[*] no bash available, cannot test afl-cmin.bash"
+ $ECHO "$GREY[*] no bash available, cannot test afl-cmin.bash"
}
fi
../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
@@ -210,7 +210,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CNT=`ls in2/* 2>/dev/null | wc -l`
case "$CNT" in
*2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
- 1) {
+ \ *1|1) { # allow leading whitecase for portability
test -s in2/* && $ECHO "$YELLOW[?] afl-cmin did minimize to one testcase. This can be a bug or due compiler optimization."
test -s in2/* || {
$ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases ($CNT)"
@@ -229,8 +229,8 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CNT=`ls in2/* 2>/dev/null | wc -l`
case "$CNT" in
*2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;;
- 1) {
- test -s in2/* && $ECHO "$YELLOW[?] afl-cmin.bash did minimize to one testcase. This can be a bug or due compiler optimization."
+ \ *1|1) { # allow leading whitecase for portability
+ test -s in2/* && $ECHO "$YELLOW[?] afl-cmin.bash did minimize to one testcase. This can be a bug or due compiler optimization."
test -s in2/* || {
$ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
CODE=1
@@ -242,7 +242,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
;;
esac
} else {
- $ECHO "$GRAY[*] no bash available, cannot test afl-cmin.bash"
+ $ECHO "$GREY[*] no bash available, cannot test afl-cmin.bash"
}
fi
../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION
index f5537ed8..2dbc30b8 100644
--- a/unicorn_mode/UNICORNAFL_VERSION
+++ b/unicorn_mode/UNICORNAFL_VERSION
@@ -1 +1 @@
-768e6bb2
+83d1b426
diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh
index f1306a06..8f6ceab7 100755
--- a/unicorn_mode/build_unicorn_support.sh
+++ b/unicorn_mode/build_unicorn_support.sh
@@ -44,7 +44,7 @@ echo "[*] Performing basic sanity checks..."
PLT=`uname -s`
-if [ ! "$PLT" = "Linux" ] && [ ! "$PLT" = "Darwin" ] && [ ! "$PLT" = "FreeBSD" ] && [ ! "$PLT" = "NetBSD" ] && [ ! "$PLT" = "OpenBSD" ]; then
+if [ ! "$PLT" = "Linux" ] && [ ! "$PLT" = "Darwin" ] && [ ! "$PLT" = "FreeBSD" ] && [ ! "$PLT" = "NetBSD" ] && [ ! "$PLT" = "OpenBSD" ] && [ ! "$PLT" = "DragonFly" ]; then
echo "[-] Error: Unicorn instrumentation is unsupported on $PLT."
exit 1
@@ -89,6 +89,12 @@ if [ "$PLT" = "FreeBSD" ]; then
TARCMD=gtar
fi
+if [ "$PLT" = "DragonFly" ]; then
+ MAKECMD=gmake
+ CORES=`sysctl -n hw.ncpu`
+ TARCMD=tar
+fi
+
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
MAKECMD=gmake
CORES=`sysctl -n hw.ncpu`
@@ -150,6 +156,7 @@ if [ $? -eq 0 ]; then
echo "[*] initializing unicornafl submodule"
git submodule init || exit 1
git submodule update ./unicornafl 2>/dev/null # ignore errors
+ git submodule sync ./unicornafl 2>/dev/null # ignore errors
else
echo "[*] cloning unicornafl"
test -d unicornafl || {
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject 8cca4801adb767dce7cf72202d7d25bdb420cf7
+Subproject 83d1b426be5d373edcc81576f58a10f617df143
diff --git a/utils/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c
index b5b8196d..087f18e8 100644
--- a/utils/afl_frida/afl-frida.c
+++ b/utils/afl_frida/afl-frida.c
@@ -153,7 +153,7 @@ static int enumerate_ranges(const GumRangeDetails *details,
}
-int main() {
+int main(int argc, char** argv) {
#ifndef __APPLE__
(void)personality(ADDR_NO_RANDOMIZE); // disable ASLR
@@ -164,105 +164,140 @@ int main() {
// If there is just one function, then there is nothing to change
// or add here.
- void *dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
+ void *dl = NULL;
+ if (argc > 2) {
+ dl = dlopen(argv[1], RTLD_LAZY);
+ } else {
+ dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
+ }
if (!dl) {
- fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
+ if (argc > 2)
+ fprintf(stderr, "Could not load %s\n", argv[1]);
+ else
+ fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
exit(-1);
}
- if (!(o_function = dlsym(dl, TARGET_FUNCTION))) {
+ if (argc > 2)
+ o_function = dlsym(dl, argv[2]);
+ else
+ o_function = dlsym(dl, TARGET_FUNCTION);
+ if (!o_function) {
- fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
+ if (argc > 2)
+ fprintf(stderr, "Could not find function %s\n", argv[2]);
+ else
+ fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
exit(-1);
}
// END STEP 2
- gum_init_embedded();
- if (!gum_stalker_is_supported()) {
-
- gum_deinit_embedded();
- return 1;
-
- }
-
- GumStalker *stalker = gum_stalker_new();
-
- GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY);
- GumMemoryRange code_range;
- gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
- &code_range);
-
- guint64 code_start = code_range.base_address;
- guint64 code_end = code_range.base_address + code_range.size;
- range_t instr_range = {0, code_start, code_end};
-
- printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
- base_address, code_start, code_end);
- if (!code_start || !code_end) {
-
- fprintf(stderr, "Error: no valid memory address found for %s\n",
- TARGET_LIBRARY);
- exit(-1);
-
- }
-
- GumStalkerTransformer *transformer =
- gum_stalker_transformer_make_from_callback(instr_basic_block,
- &instr_range, NULL);
-
- // to ensure that the signatures are not optimized out
- memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1);
- memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
- sizeof(AFL_DEFER_FORKSVR) + 1);
- __afl_manual_init();
-
- //
- // any expensive target library initialization that has to be done just once
- // - put that here
- //
-
- gum_stalker_follow_me(stalker, transformer, NULL);
-
- while (__afl_persistent_loop(UINT32_MAX) != 0) {
-
- previous_pc = 0; // Required!
-
-#ifdef _DEBUG
- fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
- hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
- fprintf(stderr, "RECV:");
- for (int i = 0; i < *__afl_fuzz_len; i++)
- fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
- fprintf(stderr, "\n");
-#endif
-
- // STEP 3: ensure the minimum length is present and setup the target
- // function to fuzz.
-
- if (*__afl_fuzz_len > 0) {
-
- __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
- (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
-
+ if (!getenv("AFL_FRIDA_TEST_INPUT")) {
+ gum_init_embedded();
+ if (!gum_stalker_is_supported()) {
+
+ gum_deinit_embedded();
+ return 1;
+
}
+
+ GumStalker *stalker = gum_stalker_new();
+
+ GumAddress base_address;
+ if (argc > 2)
+ base_address = gum_module_find_base_address(argv[1]);
+ else
+ base_address = gum_module_find_base_address(TARGET_LIBRARY);
+ GumMemoryRange code_range;
+ if (argc > 2)
+ gum_module_enumerate_ranges(argv[1], GUM_PAGE_RX, enumerate_ranges,
+ &code_range);
+ else
+ gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
+ &code_range);
+
+ guint64 code_start = code_range.base_address;
+ guint64 code_end = code_range.base_address + code_range.size;
+ range_t instr_range = {0, code_start, code_end};
+
+ printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
+ base_address, code_start, code_end);
+ if (!code_start || !code_end) {
+
+ if (argc > 2)
+ fprintf(stderr, "Error: no valid memory address found for %s\n",
+ argv[1]);
+ else
+ fprintf(stderr, "Error: no valid memory address found for %s\n",
+ TARGET_LIBRARY);
+ exit(-1);
+
+ }
+
+ GumStalkerTransformer *transformer =
+ gum_stalker_transformer_make_from_callback(instr_basic_block,
+ &instr_range, NULL);
+
+ // to ensure that the signatures are not optimized out
+ memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1);
+ memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
+ sizeof(AFL_DEFER_FORKSVR) + 1);
+ __afl_manual_init();
+
+ //
+ // any expensive target library initialization that has to be done just once
+ // - put that here
+ //
+
+ gum_stalker_follow_me(stalker, transformer, NULL);
+
+ while (__afl_persistent_loop(UINT32_MAX) != 0) {
+
+ previous_pc = 0; // Required!
+
+ #ifdef _DEBUG
+ fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
+ hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
+ fprintf(stderr, "RECV:");
+ for (int i = 0; i < *__afl_fuzz_len; i++)
+ fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
+ fprintf(stderr, "\n");
+ #endif
+
+ // STEP 3: ensure the minimum length is present and setup the target
+ // function to fuzz.
+
+ if (*__afl_fuzz_len > 0) {
+
+ __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
+ (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
+
+ }
+
+ // END STEP 3
+
+ }
+
+ gum_stalker_unfollow_me(stalker);
+
+ while (gum_stalker_garbage_collect(stalker))
+ g_usleep(10000);
+
+ g_object_unref(stalker);
+ g_object_unref(transformer);
+ gum_deinit_embedded();
- // END STEP 3
-
+ } else {
+ char buf[8*1024] = {0};
+ int count = read(0, buf, sizeof(buf));
+ buf[8*1024-1] = '\0';
+ (*o_function)(buf, count);
}
- gum_stalker_unfollow_me(stalker);
-
- while (gum_stalker_garbage_collect(stalker))
- g_usleep(10000);
-
- g_object_unref(stalker);
- g_object_unref(transformer);
- gum_deinit_embedded();
-
return 0;
}
diff --git a/utils/afl_frida/android/README.md b/utils/afl_frida/android/README.md
new file mode 100644
index 00000000..044b48a1
--- /dev/null
+++ b/utils/afl_frida/android/README.md
@@ -0,0 +1 @@
+For android, frida-gum package (ex. https://github.com/frida/frida/releases/download/14.2.6/frida-gum-devkit-14.2.6-android-arm64.tar.xz) is needed to be extracted in the directory.
diff --git a/utils/afl_frida/android/frida-gum-example.c b/utils/afl_frida/android/frida-gum-example.c
new file mode 100644
index 00000000..14d98248
--- /dev/null
+++ b/utils/afl_frida/android/frida-gum-example.c
@@ -0,0 +1,130 @@
+/*
+ * Compile with:
+ *
+ * clang -fPIC -DANDROID -ffunction-sections -fdata-sections -Os -pipe -g3 frida-gum-example.c -o frida-gum-example -L. -lfrida-gum -llog -ldl -lm -pthread -Wl,--gc-sections,-z,noexecstack,-z,relro,-z,now -fuse-ld=gold -fuse-ld=gold -Wl,--icf=all
+ *
+ * Visit https://frida.re to learn more about Frida.
+ */
+
+#include "frida-gum.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+typedef struct _ExampleListener ExampleListener;
+typedef enum _ExampleHookId ExampleHookId;
+
+struct _ExampleListener
+{
+ GObject parent;
+
+ guint num_calls;
+};
+
+enum _ExampleHookId
+{
+ EXAMPLE_HOOK_OPEN,
+ EXAMPLE_HOOK_CLOSE
+};
+
+static void example_listener_iface_init (gpointer g_iface, gpointer iface_data);
+
+#define EXAMPLE_TYPE_LISTENER (example_listener_get_type ())
+G_DECLARE_FINAL_TYPE (ExampleListener, example_listener, EXAMPLE, LISTENER, GObject)
+G_DEFINE_TYPE_EXTENDED (ExampleListener,
+ example_listener,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (GUM_TYPE_INVOCATION_LISTENER,
+ example_listener_iface_init))
+
+int
+main (int argc,
+ char * argv[])
+{
+ GumInterceptor * interceptor;
+ GumInvocationListener * listener;
+
+ gum_init_embedded ();
+
+ interceptor = gum_interceptor_obtain ();
+ listener = g_object_new (EXAMPLE_TYPE_LISTENER, NULL);
+
+ gum_interceptor_begin_transaction (interceptor);
+ gum_interceptor_attach (interceptor,
+ GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "open")),
+ listener,
+ GSIZE_TO_POINTER (EXAMPLE_HOOK_OPEN));
+ gum_interceptor_attach (interceptor,
+ GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "close")),
+ listener,
+ GSIZE_TO_POINTER (EXAMPLE_HOOK_CLOSE));
+ gum_interceptor_end_transaction (interceptor);
+
+ close (open ("/etc/hosts", O_RDONLY));
+ close (open ("/etc/fstab", O_RDONLY));
+
+ g_print ("[*] listener got %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
+
+ gum_interceptor_detach (interceptor, listener);
+
+ close (open ("/etc/hosts", O_RDONLY));
+ close (open ("/etc/fstab", O_RDONLY));
+
+ g_print ("[*] listener still has %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
+
+ g_object_unref (listener);
+ g_object_unref (interceptor);
+
+ gum_deinit_embedded ();
+
+ return 0;
+}
+
+static void
+example_listener_on_enter (GumInvocationListener * listener,
+ GumInvocationContext * ic)
+{
+ ExampleListener * self = EXAMPLE_LISTENER (listener);
+ ExampleHookId hook_id = GUM_IC_GET_FUNC_DATA (ic, ExampleHookId);
+
+ switch (hook_id)
+ {
+ case EXAMPLE_HOOK_OPEN:
+ g_print ("[*] open(\"%s\")\n", (const gchar *) gum_invocation_context_get_nth_argument (ic, 0));
+ break;
+ case EXAMPLE_HOOK_CLOSE:
+ g_print ("[*] close(%d)\n", GPOINTER_TO_INT (gum_invocation_context_get_nth_argument (ic, 0)));
+ break;
+ }
+
+ self->num_calls++;
+}
+
+static void
+example_listener_on_leave (GumInvocationListener * listener,
+ GumInvocationContext * ic)
+{
+}
+
+static void
+example_listener_class_init (ExampleListenerClass * klass)
+{
+ (void) EXAMPLE_IS_LISTENER;
+ (void) glib_autoptr_cleanup_ExampleListener;
+}
+
+static void
+example_listener_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GumInvocationListenerInterface * iface = g_iface;
+
+ iface->on_enter = example_listener_on_enter;
+ iface->on_leave = example_listener_on_leave;
+}
+
+static void
+example_listener_init (ExampleListener * self)
+{
+}
diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c
index 513dc8f2..fe225416 100644
--- a/utils/afl_network_proxy/afl-network-server.c
+++ b/utils/afl_network_proxy/afl-network-server.c
@@ -24,10 +24,6 @@
#define AFL_MAIN
-#ifdef __ANDROID__
- #include "android-ashmem.h"
-#endif
-
#include "config.h"
#include "types.h"
#include "debug.h"
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index c6f5a76c..30e6ebb9 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -1,12 +1,8 @@
-//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===//
//===----------------------------------------------------------------------===//
/* This file allows to fuzz libFuzzer-style target functions
- (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
+ (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing.
Usage:
################################################################################
@@ -25,25 +21,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
EOF
# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
-clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c
+clang -c aflpp_driver.c
# Build afl-compiler-rt.o.c from the AFL distribution.
-clang -c -w $AFL_HOME/instrumentation/afl-compiler-rt.o.c
+clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c
# Build this file, link it with afl-compiler-rt.o.o and the target code.
-clang++ afl_driver.cpp test_fuzzer.o afl-compiler-rt.o.o
+afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o
# Run AFL:
rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
################################################################################
-AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
-specified. If the file does not exist, it is created. This is useful for getting
-stack traces (when using ASAN for example) or original error messages on hard
-to reproduce bugs. Note that any content written to stderr will be written to
-this file instead of stderr's usual location.
-
-AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
-If 1, close stdout at startup. If 2 close stderr; if 3 close both.
-
*/
+
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
@@ -65,47 +53,6 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
#include "hash.h"
#endif
-#ifndef MAP_FIXED_NOREPLACE
- #define MAP_FIXED_NOREPLACE 0x100000
-#endif
-
-#define MAX_DUMMY_SIZE 256000
-
-// Platform detection. Copied from FuzzerInternal.h
-#ifdef __linux__
- #define LIBFUZZER_LINUX 1
- #define LIBFUZZER_APPLE 0
- #define LIBFUZZER_NETBSD 0
- #define LIBFUZZER_FREEBSD 0
- #define LIBFUZZER_OPENBSD 0
-#elif __APPLE__
- #define LIBFUZZER_LINUX 0
- #define LIBFUZZER_APPLE 1
- #define LIBFUZZER_NETBSD 0
- #define LIBFUZZER_FREEBSD 0
- #define LIBFUZZER_OPENBSD 0
-#elif __NetBSD__
- #define LIBFUZZER_LINUX 0
- #define LIBFUZZER_APPLE 0
- #define LIBFUZZER_NETBSD 1
- #define LIBFUZZER_FREEBSD 0
- #define LIBFUZZER_OPENBSD 0
-#elif __FreeBSD__
- #define LIBFUZZER_LINUX 0
- #define LIBFUZZER_APPLE 0
- #define LIBFUZZER_NETBSD 0
- #define LIBFUZZER_FREEBSD 1
- #define LIBFUZZER_OPENBSD 0
-#elif __OpenBSD__
- #define LIBFUZZER_LINUX 0
- #define LIBFUZZER_APPLE 0
- #define LIBFUZZER_NETBSD 0
- #define LIBFUZZER_FREEBSD 0
- #define LIBFUZZER_OPENBSD 1
-#else
- #error "Support for your platform has not been implemented"
-#endif
-
int __afl_sharedmem_fuzzing = 1;
extern unsigned int * __afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr;
diff --git a/utils/defork/defork.c b/utils/defork/defork.c
index f71d1124..f50b9a4b 100644
--- a/utils/defork/defork.c
+++ b/utils/defork/defork.c
@@ -1,4 +1,4 @@
-#define __GNU_SOURCE
+#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
diff --git a/utils/libdislocator/README.md b/utils/libdislocator/README.md
index 1785463e..d0340af0 100644
--- a/utils/libdislocator/README.md
+++ b/utils/libdislocator/README.md
@@ -1,6 +1,6 @@
# libdislocator, an abusive allocator
- (See ../README.md for the general instruction manual.)
+ (See ../../README.md for the general instruction manual.)
This is a companion library that can be used as a drop-in replacement for the
libc allocator in the fuzzed binaries. It improves the odds of bumping into
diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c
index 2324e390..c041fec6 100644
--- a/utils/libdislocator/libdislocator.so.c
+++ b/utils/libdislocator/libdislocator.so.c
@@ -345,10 +345,10 @@ void free(void *ptr) {
len = PTR_L(ptr);
total_mem -= len;
+ u8 *ptr_ = ptr;
if (align_allocations && (len & (ALLOC_ALIGN_SIZE - 1))) {
- u8 * ptr_ = ptr;
size_t rlen = (len & ~(ALLOC_ALIGN_SIZE - 1)) + ALLOC_ALIGN_SIZE;
for (; len < rlen; ++len)
if (ptr_[len] != TAIL_ALLOC_CANARY)
@@ -359,11 +359,13 @@ void free(void *ptr) {
/* Protect everything. Note that the extra page at the end is already
set as PROT_NONE, so we don't need to touch that. */
- ptr -= PAGE_SIZE * PG_COUNT(len + 8) - len - 8;
+ ptr_ -= PAGE_SIZE * PG_COUNT(len + 8) - len - 8;
- if (mprotect(ptr - 8, PG_COUNT(len + 8) * PAGE_SIZE, PROT_NONE))
+ if (mprotect(ptr_ - 8, PG_COUNT(len + 8) * PAGE_SIZE, PROT_NONE))
FATAL("mprotect() failed when freeing memory");
+ ptr = ptr_;
+
/* Keep the mapping; this is wasteful, but prevents ptr reuse. */
}
diff --git a/utils/libtokencap/README.md b/utils/libtokencap/README.md
index 13a440da..a39ed3a5 100644
--- a/utils/libtokencap/README.md
+++ b/utils/libtokencap/README.md
@@ -1,6 +1,11 @@
# strcmp() / memcmp() token capture library
- (See ../README.md for the general instruction manual.)
+ NOTE: libtokencap is only recommended for binary-only targets or targets that
+ do not compile with afl-clang-fast/afl-clang-lto.
+ The afl-clang-fast AFL_LLVM_DICT2FILE feature is much better, afl-clang-lto
+ has that feature automatically integrated.
+
+ (See ../../README.md for the general instruction manual.)
This companion library allows you to instrument `strcmp()`, `memcmp()`,
and related functions to automatically extract syntax tokens passed to any of
diff --git a/utils/persistent_mode/Makefile b/utils/persistent_mode/Makefile
index 6fa1c30e..e348c46c 100644
--- a/utils/persistent_mode/Makefile
+++ b/utils/persistent_mode/Makefile
@@ -1,10 +1,10 @@
all:
- afl-clang-fast -o persistent_demo persistent_demo.c
- afl-clang-fast -o persistent_demo_new persistent_demo_new.c
- AFL_DONT_OPTIMIZE=1 afl-clang-fast -o test-instr test-instr.c
+ ../../afl-clang-fast -o persistent_demo persistent_demo.c
+ ../../afl-clang-fast -o persistent_demo_new persistent_demo_new.c
+ AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -o test-instr test-instr.c
document:
- AFL_DONT_OPTIMIZE=1 afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c
+ AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c
clean:
rm -f persistent_demo persistent_demo_new test-instr
diff --git a/utils/qemu_persistent_hook/test.c b/utils/qemu_persistent_hook/test.c
index afeff202..a0e815dc 100644
--- a/utils/qemu_persistent_hook/test.c
+++ b/utils/qemu_persistent_hook/test.c
@@ -2,7 +2,7 @@
int target_func(unsigned char *buf, int size) {
- printf("buffer:%p, size:%p\n", buf, size);
+ printf("buffer:%p, size:%d\n", buf, size);
switch (buf[0]) {
case 1: