mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
Merge branch 'dev' of github.com:vanhauser-thc/AFLplusplus into dev
This commit is contained in:
@ -10,7 +10,7 @@ AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
@ -29,14 +29,14 @@ CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
|
||||
if CLANG_FORMAT_BIN is None:
|
||||
o = 0
|
||||
try:
|
||||
p = subprocess.Popen(["clang-format-8", "--version"], stdout=subprocess.PIPE)
|
||||
p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE)
|
||||
o, _ = p.communicate()
|
||||
o = str(o, "utf-8")
|
||||
o = o[len("clang-format version "):].strip()
|
||||
o = o[:o.find(".")]
|
||||
o = int(o)
|
||||
except:
|
||||
print ("clang-format-8 is needed. Aborted.")
|
||||
print ("clang-format-10 is needed. Aborted.")
|
||||
exit(1)
|
||||
#if o < 7:
|
||||
# if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
|
||||
@ -51,7 +51,7 @@ if CLANG_FORMAT_BIN is None:
|
||||
# print ("clang-format 7 or above is needed. Aborted.")
|
||||
# exit(1)
|
||||
else:
|
||||
CLANG_FORMAT_BIN = 'clang-format-8'
|
||||
CLANG_FORMAT_BIN = 'clang-format-10'
|
||||
|
||||
COLUMN_LIMIT = 80
|
||||
for line in fmt.split("\n"):
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,7 +42,6 @@ qemu_mode/libcompcov/compcovtest
|
||||
as
|
||||
ld
|
||||
qemu_mode/qemu-*
|
||||
unicorn_mode/unicornafl/
|
||||
unicorn_mode/samples/*/\.test-*
|
||||
unicorn_mode/samples/*/output/
|
||||
core\.*
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "unicorn_mode/unicornafl"]
|
||||
path = unicorn_mode/unicornafl
|
||||
url = https://github.com/AFLplusplus/unicornafl.git
|
@ -41,8 +41,8 @@ before_install:
|
||||
# export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
|
||||
- echo Testing on $NAME
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y git libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y git libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi
|
||||
|
||||
script:
|
||||
- gcc -v
|
||||
|
46
GNUmakefile
46
GNUmakefile
@ -59,7 +59,7 @@ ifneq "$(shell uname)" "Darwin"
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname -m)" "x86_64"
|
||||
ifneq "$(shell uname -m)" "i386"
|
||||
ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386"
|
||||
ifneq "$(shell uname -m)" "amd64"
|
||||
ifneq "$(shell uname -m)" "i86pc"
|
||||
AFL_NO_X86=1
|
||||
@ -150,6 +150,14 @@ ifdef NO_PYTHON
|
||||
PYFLAGS=
|
||||
endif
|
||||
|
||||
IN_REPO=0
|
||||
ifeq "$(shell git status >/dev/null 2>&1 && echo 1 || echo 0)" "1"
|
||||
IN_REPO=1
|
||||
endif
|
||||
ifeq "$(shell svn proplist . 2>/dev/null && echo 1 || echo 0)" "1"
|
||||
IN_REPO=1
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(info Compiling static version of binaries)
|
||||
# Disable python for static compilation to simplify things
|
||||
@ -214,7 +222,8 @@ help:
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
|
||||
@echo "clean: cleans everything compiled (not downloads when on a checkout)"
|
||||
@echo "deepclean: cleans everything including downloads"
|
||||
@echo "code-format: format the code, do this before you commit and send a PR please!"
|
||||
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
|
||||
@echo "unit: perform unit tests (based on cmocka)"
|
||||
@ -316,7 +325,7 @@ afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# document all mutations and only do one run (use with only one input file!)
|
||||
@ -324,27 +333,27 @@ document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/
|
||||
$(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
|
||||
|
||||
test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
|
||||
|
||||
unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
|
||||
$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_maybe_alloc
|
||||
|
||||
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
|
||||
|
||||
unit_list: test/unittests/unit_list.o
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_list
|
||||
|
||||
test/unittests/preallocable.o : $(COMM_HDR) include/afl-prealloc.h test/unittests/preallocable.c $(AFL_FUZZ_FILES)
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o
|
||||
|
||||
unit_preallocable: test/unittests/unit_preallocable.o
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_preallocable
|
||||
|
||||
unit_clean:
|
||||
@ -401,10 +410,10 @@ all_done: test_build
|
||||
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
.NOTPARALLEL: clean all
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
@ -415,7 +424,18 @@ clean:
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C src/third_party/libradamsa/ clean
|
||||
-rm -rf unicorn_mode/unicornafl
|
||||
rm -rf qemu_mode/qemu-3.1.1
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
$(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||
else
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
endif
|
||||
|
||||
deepclean: clean
|
||||
rm -rf qemu_mode/qemu-3.1.1.tar.xz
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
git reset --hard >/dev/null 2>&1 || true
|
||||
|
||||
distrib: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||

|
||||
|
||||
Release Version: [2.63c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release Version: [2.64c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
Github Version: 2.63d
|
||||
Github Version: 2.64d
|
||||
|
||||
includes all necessary/interesting changes from Google's afl 2.56b
|
||||
|
||||
@ -160,7 +160,8 @@ These build targets exist:
|
||||
* distrib: everything (for both binary-only and source code fuzzing)
|
||||
* man: creates simple man pages from the help option of the programs
|
||||
* install: installs everything you have compiled with the build options above
|
||||
* clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well
|
||||
* clean: cleans everything compiled, not downloads (unless not on a checkout)
|
||||
* deepclean: cleans everything including downloads
|
||||
* code-format: format the code, do this before you commit and send a PR please!
|
||||
* tests: runs test cases to ensure that all features are still working as they should
|
||||
* unit: perform unit tests (based on cmocka)
|
||||
|
5
TODO.md
5
TODO.md
@ -1,11 +1,12 @@
|
||||
# TODO list for AFL++
|
||||
|
||||
## Roadmap 2.64
|
||||
## Roadmap 2.65
|
||||
|
||||
- AFL_MAP_SIZE for afl-llvm-pass, qemu_mode and unicorn_mode
|
||||
- fix stability calculation bug
|
||||
- random crc32 HASH_CONST per run? because with 65536 paths we have collisions
|
||||
- namespace for targets? e.g. network
|
||||
- libradamsa as a custom module?
|
||||
- fix stability calculation bug
|
||||
|
||||
## Further down the road
|
||||
|
||||
|
@ -9,24 +9,42 @@ 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 ++2.63d (development):
|
||||
### Version ++2.64d (develop):
|
||||
- qemu_mode:
|
||||
- add information on PIE/PIC load addresses for 32 bit
|
||||
- better dependency checks
|
||||
- gcc_plugin:
|
||||
- better dependency checks
|
||||
- unicorn_mode:
|
||||
- better submodule handling
|
||||
- all:
|
||||
- fix 32 bit build options
|
||||
- make clean now leaves qemu-3.1.1.tar.xz and the unicornafl directory
|
||||
intact if in a git/svn checkout - unless "deepclean" is used
|
||||
|
||||
|
||||
### Version ++2.64c (release):
|
||||
- llvm_mode LTO mode:
|
||||
- now requires llvm11 - but compiles all targets! :)
|
||||
- autodictionary feature added, enable with AFL_LLVM_LTO_AUTODICTIONARY
|
||||
- autodictionary feature added, enable with `AFL_LLVM_LTO_AUTODICTIONARY`
|
||||
- variable map size usage
|
||||
- afl-fuzz:
|
||||
- variable map size support added (only LTO mode can use this)
|
||||
- snapshot feature usage now visible in UI
|
||||
- Now setting "-L -1" will enable MOpt in parallel to normal mutation.
|
||||
Additionally this allows to run dictionaries, radamsa and cmplog.
|
||||
- Now setting `-L -1` will enable MOpt in parallel to normal mutation.
|
||||
Additionally, this allows to run dictionaries, radamsa and cmplog.
|
||||
- fix for cmplog/redqueen mode if stdin was used
|
||||
- fix for writing a better plot_data file
|
||||
- qemu_mode: fix for persistent mode (which would not terminate or get stuck)
|
||||
- compare-transform/AFL_LLVM_LAF_TRANSFORM_COMPARES now transforms also
|
||||
static global and local variable comparisons (cannot find all though)
|
||||
- extended forkserver: map_size and more information is communicated to
|
||||
afl-fuzz (and afl-fuzz acts accordingly)
|
||||
- more refactoring
|
||||
- new environment variable: AFL_MAP_SIZE to specify the size of the shared map
|
||||
- if AFL_CC/AFL_CXX is set but empty afl compilers did fail, fixed
|
||||
(this bug is in vanilla afl too)
|
||||
- added NO_PYTHON flag to disable python support when building afl-fuzz
|
||||
- more refactoring
|
||||
|
||||
|
||||
### Version ++2.63c (release):
|
||||
@ -137,7 +155,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
- AFL_PERSISTENT_HOOK callback module for persistent QEMU
|
||||
(see examples/qemu_persistent_hook)
|
||||
- added qemu_mode/README.persistent.md documentation
|
||||
- AFL_ENTRYPOINT noew has instruction granularity
|
||||
- AFL_ENTRYPOINT now has instruction granularity
|
||||
- afl-cmin is now a sh script (invoking awk) instead of bash for portability
|
||||
the original script is still present as afl-cmin.bash
|
||||
- afl-showmap: -i dir option now allows processing multiple inputs using the
|
||||
|
@ -243,6 +243,11 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
normally indicated by the cycle counter in the UI turning green. May be
|
||||
convenient for some types of automated jobs.
|
||||
|
||||
- AFL_MAP_SIZE sets the size of the shared map that afl-fuzz, afl-showmap,
|
||||
afl-tmin and afl-analyze create to gather instrumentation data from
|
||||
the target. This must be equal or larger than the size the target was
|
||||
compiled with.
|
||||
|
||||
- Setting AFL_NO_AFFINITY disables attempts to bind to a specific CPU core
|
||||
on Linux systems. This slows things down, but lets you run more instances
|
||||
of afl-fuzz than would be prudent (if you really want to).
|
||||
|
@ -44,10 +44,10 @@ M32FLAG=$(___M32FLAG)
|
||||
all: argvfuzz32.so argvfuzz64.so
|
||||
|
||||
argvfuzz32.so: argvfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
|
||||
-@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)"
|
||||
|
||||
argvfuzz64.so: argvfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)"
|
||||
-@$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz64 build failure (that's fine)"
|
||||
|
||||
install: argvfuzz32.so argvfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
|
@ -16,7 +16,8 @@ int target_func(unsigned char *buf, int size) {
|
||||
}
|
||||
|
||||
break;
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,10 @@ M32FLAG=$(___M32FLAG)
|
||||
all: socketfuzz32.so socketfuzz64.so
|
||||
|
||||
socketfuzz32.so: socketfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
|
||||
-@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "socketfuzz32 build failure (that's fine)"
|
||||
|
||||
socketfuzz64.so: socketfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)"
|
||||
-@$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "socketfuzz64 build failure (that's fine)"
|
||||
|
||||
install: socketfuzz32.so socketfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
|
@ -364,6 +364,16 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
u8 *ptr;
|
||||
if (!be_quiet &&
|
||||
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
|
||||
|
||||
u32 map_size = atoi(ptr);
|
||||
if (map_size != MAP_SIZE)
|
||||
FATAL("AFL_MAP_SIZE is not supported by afl-gcc-fast");
|
||||
|
||||
}
|
||||
|
||||
check_environment_vars(envp);
|
||||
|
||||
find_obj(argv[0]);
|
||||
|
@ -443,11 +443,11 @@ typedef struct afl_state {
|
||||
fast_cal, /* Try to calibrate faster? */
|
||||
disable_trim; /* Never trim in fuzz_one */
|
||||
|
||||
u8 virgin_bits[MAP_SIZE], /* Regions yet untouched by fuzzing */
|
||||
virgin_tmout[MAP_SIZE], /* Bits we haven't seen in tmouts */
|
||||
virgin_crash[MAP_SIZE]; /* Bits we haven't seen in crashes */
|
||||
u8 *virgin_bits, /* Regions yet untouched by fuzzing */
|
||||
*virgin_tmout, /* Bits we haven't seen in tmouts */
|
||||
*virgin_crash; /* Bits we haven't seen in crashes */
|
||||
|
||||
u8 var_bytes[MAP_SIZE]; /* Bytes that appear to be variable */
|
||||
u8 *var_bytes; /* Bytes that appear to be variable */
|
||||
|
||||
volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
clear_screen; /* Window resized? */
|
||||
@ -535,7 +535,7 @@ typedef struct afl_state {
|
||||
*queue_top, /* Top of the list */
|
||||
*q_prev100; /* Previous 100 marker */
|
||||
|
||||
struct queue_entry *top_rated[MAP_SIZE]; /* Top entries for bitmap bytes */
|
||||
struct queue_entry **top_rated; /* Top entries for bitmap bytes */
|
||||
|
||||
struct extra_data *extras; /* Extra tokens to fuzz with */
|
||||
u32 extras_cnt; /* Total number of tokens read */
|
||||
@ -584,9 +584,9 @@ typedef struct afl_state {
|
||||
u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs;
|
||||
double stats_avg_exec;
|
||||
|
||||
u8 clean_trace[MAP_SIZE];
|
||||
u8 clean_trace_custom[MAP_SIZE];
|
||||
u8 first_trace[MAP_SIZE];
|
||||
u8 *clean_trace;
|
||||
u8 *clean_trace_custom;
|
||||
u8 *first_trace;
|
||||
|
||||
/*needed for afl_fuzz_one */
|
||||
// TODO: see which we can reuse
|
||||
@ -608,6 +608,10 @@ typedef struct afl_state {
|
||||
u8 * ex_buf;
|
||||
size_t ex_size;
|
||||
|
||||
/* this is a fixed buffer of size map_size that can be used by any function if
|
||||
* they do not call another function */
|
||||
u8 *map_tmp_buf;
|
||||
|
||||
} afl_state_t;
|
||||
|
||||
/* A global pointer to all instances is needed (for now) for signals to arrive
|
||||
@ -794,7 +798,7 @@ struct custom_mutator {
|
||||
|
||||
};
|
||||
|
||||
void afl_state_init(afl_state_t *);
|
||||
void afl_state_init(afl_state_t *, uint32_t map_size);
|
||||
void afl_state_deinit(afl_state_t *);
|
||||
void read_afl_environment(afl_state_t *, char **);
|
||||
|
||||
@ -953,7 +957,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
|
||||
|
||||
static inline u32 get_rand_seed(afl_state_t *afl) {
|
||||
|
||||
if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed;
|
||||
if (unlikely(afl->fixed_seed)) { return (u32)afl->init_seed; }
|
||||
return afl->rand_seed[0];
|
||||
|
||||
}
|
||||
@ -964,8 +968,12 @@ static inline u32 get_rand_seed(afl_state_t *afl) {
|
||||
static inline u64 next_p2(u64 val) {
|
||||
|
||||
u64 ret = 1;
|
||||
while (val > ret)
|
||||
while (val > ret) {
|
||||
|
||||
ret <<= 1;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ static inline void *DFL_ck_alloc_nozero(u32 size) {
|
||||
|
||||
void *ret;
|
||||
|
||||
if (!size) return NULL;
|
||||
if (!size) { return NULL; }
|
||||
|
||||
ALLOC_CHECK_SIZE(size);
|
||||
ret = malloc(size);
|
||||
@ -103,7 +103,7 @@ static inline void *DFL_ck_alloc(u32 size) {
|
||||
|
||||
void *mem;
|
||||
|
||||
if (!size) return NULL;
|
||||
if (!size) { return NULL; }
|
||||
mem = DFL_ck_alloc_nozero(size);
|
||||
|
||||
return memset(mem, 0, size);
|
||||
@ -115,7 +115,7 @@ static inline void *DFL_ck_alloc(u32 size) {
|
||||
|
||||
static inline void DFL_ck_free(void *mem) {
|
||||
|
||||
if (!mem) return;
|
||||
if (!mem) { return; }
|
||||
|
||||
free(mem);
|
||||
|
||||
@ -165,7 +165,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) {
|
||||
u8 *ret;
|
||||
u32 size;
|
||||
|
||||
if (!str) return NULL;
|
||||
if (!str) { return NULL; }
|
||||
|
||||
size = strlen((char *)str) + 1;
|
||||
|
||||
@ -184,7 +184,7 @@ static inline void *DFL_ck_memdup(void *mem, u32 size) {
|
||||
|
||||
void *ret;
|
||||
|
||||
if (!mem || !size) return NULL;
|
||||
if (!mem || !size) { return NULL; }
|
||||
|
||||
ALLOC_CHECK_SIZE(size);
|
||||
ret = malloc(size);
|
||||
@ -201,7 +201,7 @@ static inline u8 *DFL_ck_memdup_str(u8 *mem, u32 size) {
|
||||
|
||||
u8 *ret;
|
||||
|
||||
if (!mem || !size) return NULL;
|
||||
if (!mem || !size) { return NULL; }
|
||||
|
||||
ALLOC_CHECK_SIZE(size);
|
||||
ret = malloc(size + 1);
|
||||
@ -772,8 +772,12 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func,
|
||||
*/
|
||||
static inline size_t next_pow2(size_t in) {
|
||||
|
||||
if (in == 0 || in > (size_t)-1)
|
||||
if (in == 0 || in > (size_t)-1) {
|
||||
|
||||
return 0; /* avoid undefined behaviour under-/overflow */
|
||||
|
||||
}
|
||||
|
||||
size_t out = in - 1;
|
||||
out |= out >> 1;
|
||||
out |= out >> 2;
|
||||
@ -794,10 +798,10 @@ static inline size_t next_pow2(size_t in) {
|
||||
static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
|
||||
|
||||
/* No need to realloc */
|
||||
if (likely(size_needed && *size >= size_needed)) return *buf;
|
||||
if (likely(size_needed && *size >= size_needed)) { return *buf; }
|
||||
|
||||
/* No initial size was set */
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; }
|
||||
|
||||
/* grow exponentially */
|
||||
size_t next_size = next_pow2(size_needed);
|
||||
@ -824,13 +828,13 @@ static inline void *ck_maybe_grow(void **buf, size_t *size,
|
||||
size_t size_needed) {
|
||||
|
||||
/* Oops. found a bug? */
|
||||
if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size");
|
||||
if (unlikely(size_needed < 1)) { FATAL("cannot grow to non-positive size"); }
|
||||
|
||||
/* No need to realloc */
|
||||
if (likely(*size >= size_needed)) return *buf;
|
||||
if (likely(*size >= size_needed)) { return *buf; }
|
||||
|
||||
/* No initial size was set */
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; }
|
||||
|
||||
/* grow exponentially */
|
||||
size_t next_size = next_pow2(size_needed);
|
||||
|
@ -26,6 +26,8 @@
|
||||
#ifndef _ANDROID_ASHMEM_H
|
||||
#define _ANDROID_ASHMEM_H
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/ashmem.h>
|
||||
@ -38,6 +40,7 @@
|
||||
#define shmdt bionic_shmdt
|
||||
#define shmget bionic_shmget
|
||||
#endif
|
||||
|
||||
#include <sys/shm.h>
|
||||
#undef shmat
|
||||
#undef shmctl
|
||||
@ -103,5 +106,7 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
|
||||
|
||||
}
|
||||
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -115,5 +115,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
|
||||
u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms,
|
||||
volatile u8 *stop_soon_p);
|
||||
|
||||
u32 get_map_size();
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, d = volatile github dev, e = experimental branch
|
||||
#define VERSION "++2.63d"
|
||||
#define VERSION "++2.64d"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -407,8 +407,7 @@
|
||||
#define FS_OPT_SNAPSHOT 0x20000000
|
||||
#define FS_OPT_AUTODICT 0x10000000
|
||||
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
|
||||
#define FS_OPT_SET_MAPSIZE(x) \
|
||||
(x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1))
|
||||
#define FS_OPT_SET_MAPSIZE(x) (x <= 1 || x > 0x1000000 ? 0 : ((x - 1) << 1))
|
||||
|
||||
#endif /* ! _HAVE_CONFIG_H */
|
||||
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct afl_forkserver {
|
||||
|
||||
/* a program that includes afl-forkserver needs to define these */
|
||||
|
@ -83,7 +83,7 @@ static inline void list_append(list_t *list, void *el) {
|
||||
element_t *el_box = NULL;
|
||||
PRE_ALLOC(el_box, list->element_prealloc_buf, LIST_PREALLOC_SIZE,
|
||||
list->element_prealloc_count);
|
||||
if (!el_box) FATAL("failed to allocate list element");
|
||||
if (!el_box) { FATAL("failed to allocate list element"); }
|
||||
el_box->data = el;
|
||||
el_box->next = head;
|
||||
el_box->prev = head->prev;
|
||||
|
@ -28,6 +28,8 @@
|
||||
#ifndef __AFL_SHAREDMEM_H
|
||||
#define __AFL_SHAREDMEM_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef struct sharedmem {
|
||||
|
||||
// extern unsigned char *trace_bits;
|
||||
@ -44,8 +46,7 @@ typedef struct sharedmem {
|
||||
|
||||
u8 *map; /* shared memory region */
|
||||
|
||||
size_t size_alloc; /* actual allocated size */
|
||||
size_t size_used; /* in use by shmem app */
|
||||
size_t map_size; /* actual allocated size */
|
||||
|
||||
int cmplog_mode;
|
||||
struct cmp_map *cmp_map;
|
||||
|
@ -183,6 +183,9 @@ static void *__dislocator_alloc(size_t len) {
|
||||
else
|
||||
rlen = len;
|
||||
|
||||
/* We will also store buffer length and a canary below the actual buffer, so
|
||||
let's add 8 bytes for that. */
|
||||
|
||||
tlen = (1 + PG_COUNT(rlen + 8)) * PAGE_SIZE;
|
||||
flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
fd = -1;
|
||||
@ -200,9 +203,6 @@ static void *__dislocator_alloc(size_t len) {
|
||||
(void)sp;
|
||||
#endif
|
||||
|
||||
/* We will also store buffer length and a canary below the actual buffer, so
|
||||
let's add 8 bytes for that. */
|
||||
|
||||
ret = (u8 *)mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0);
|
||||
#if defined(USEHUGEPAGE)
|
||||
/* We try one more time with regular call */
|
||||
@ -296,10 +296,6 @@ void *calloc(size_t elem_len, size_t elem_cnt) {
|
||||
|
||||
}
|
||||
|
||||
/* TODO: add a wrapper for posix_memalign, otherwise apps who use it,
|
||||
will fail when freeing the memory.
|
||||
*/
|
||||
|
||||
/* The wrapper for malloc(). Roughly the same, also clobbers the returned
|
||||
memory (unlike calloc(), malloc() is not guaranteed to return zeroed
|
||||
memory). */
|
||||
@ -468,6 +464,16 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) {
|
||||
|
||||
}
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
size_t malloc_usable_size(void *ptr) {
|
||||
#else
|
||||
size_t malloc_usable_size(const void *ptr) {
|
||||
#endif
|
||||
|
||||
return ptr ? PTR_L(ptr) : 0;
|
||||
|
||||
}
|
||||
|
||||
__attribute__((constructor)) void __dislocator_init(void) {
|
||||
|
||||
u8 *tmp = (u8 *)getenv("AFL_LD_LIMIT_MB");
|
||||
@ -492,4 +498,3 @@ __attribute__((constructor)) void __dislocator_init(void) {
|
||||
align_allocations = !!getenv("AFL_ALIGNED_ALLOC");
|
||||
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,8 @@ static void __tokencap_dump(const u8 *ptr, size_t len, u8 is_text) {
|
||||
pos += 4;
|
||||
break;
|
||||
|
||||
default: buf[pos++] = ptr[i];
|
||||
default:
|
||||
buf[pos++] = ptr[i];
|
||||
|
||||
}
|
||||
|
||||
|
@ -223,10 +223,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if ((!(getenv("AFL_LLVM_LTO_AUTODICTIONARY") // disabled when autodictionary
|
||||
&& instrument_mode != INSTRUMENT_LTO)) // and lto_mode is used
|
||||
&& (getenv("LAF_TRANSFORM_COMPARES") ||
|
||||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES"))) {
|
||||
if (getenv("LAF_TRANSFORM_COMPARES") ||
|
||||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
|
||||
|
||||
if (!be_quiet && getenv("AFL_LLVM_LTO_AUTODICTIONARY") &&
|
||||
instrument_mode != INSTRUMENT_LTO)
|
||||
WARNF(
|
||||
"using AFL_LLVM_LAF_TRANSFORM_COMPARES together with "
|
||||
"AFL_LLVM_LTO_AUTODICTIONARY makes no sense. Use only "
|
||||
"AFL_LLVM_LTO_AUTODICTIONARY.");
|
||||
|
||||
cc_params[cc_par_cnt++] = "-Xclang";
|
||||
cc_params[cc_par_cnt++] = "-load";
|
||||
@ -716,30 +721,30 @@ int main(int argc, char **argv, char **envp) {
|
||||
"Environment variables used:\n"
|
||||
"AFL_CC: path to the C compiler to use\n"
|
||||
"AFL_CXX: path to the C++ compiler to use\n"
|
||||
"AFL_PATH: path to instrumenting pass and runtime "
|
||||
"(afl-llvm-rt.*o)\n"
|
||||
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
|
||||
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
|
||||
"AFL_INST_RATIO: percentage of branches to instrument\n"
|
||||
"AFL_QUIET: suppress verbose output\n"
|
||||
"AFL_DEBUG: enable developer debugging output\n"
|
||||
"AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
|
||||
"AFL_HARDEN: adds code hardening to catch memory bugs\n"
|
||||
"AFL_USE_ASAN: activate address sanitizer\n"
|
||||
"AFL_USE_MSAN: activate memory sanitizer\n"
|
||||
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
|
||||
"AFL_USE_CFISAN: activate control flow sanitizer\n"
|
||||
"AFL_LLVM_WHITELIST: enable whitelisting (selective "
|
||||
"instrumentation)\n"
|
||||
"AFL_INST_RATIO: percentage of branches to instrument\n"
|
||||
"AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
|
||||
"AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n"
|
||||
"AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n"
|
||||
"AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison "
|
||||
"function calls\n"
|
||||
" to cascaded comparisons\n"
|
||||
"AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to "
|
||||
"cascaded "
|
||||
"comp.\n"
|
||||
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n",
|
||||
"AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n"
|
||||
" to cascaded comparisons\n"
|
||||
"AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison "
|
||||
"function calls\n"
|
||||
"AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n"
|
||||
"AFL_LLVM_WHITELIST: enable whitelisting (selective "
|
||||
"instrumentation)\n"
|
||||
"AFL_NO_BUILTIN: compile for use with libtokencap.so\n"
|
||||
"AFL_PATH: path to instrumenting pass and runtime "
|
||||
"(afl-llvm-rt.*o)\n"
|
||||
"AFL_QUIET: suppress verbose output\n"
|
||||
"AFL_USE_ASAN: activate address sanitizer\n"
|
||||
"AFL_USE_CFISAN: activate control flow sanitizer\n"
|
||||
"AFL_USE_MSAN: activate memory sanitizer\n"
|
||||
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n",
|
||||
callname, BIN_PATH, BIN_PATH);
|
||||
|
||||
SAYF(
|
||||
@ -747,21 +752,21 @@ int main(int argc, char **argv, char **envp) {
|
||||
"AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n"
|
||||
"AFL_LLVM_INSTRUMENT: set instrumentation mode: DEFAULT, CFG "
|
||||
"(INSTRIM), LTO, CTX, NGRAM-2 ... NGRAM-16\n"
|
||||
"You can also use the old environment variables:"
|
||||
"AFL_LLVM_CTX: use context sensitive coverage\n"
|
||||
"AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
|
||||
"AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage\n"
|
||||
"AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
|
||||
"AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed (sub "
|
||||
" You can also use the old environment variables instead:"
|
||||
" AFL_LLVM_CTX: use context sensitive coverage\n"
|
||||
" AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
|
||||
" AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage\n"
|
||||
" AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n"
|
||||
" AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed (sub "
|
||||
"option to INSTRIM)\n");
|
||||
|
||||
#ifdef AFL_CLANG_FLTO
|
||||
SAYF(
|
||||
"\nafl-clang-lto specific environment variables:\n"
|
||||
"AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
|
||||
"bb\n"
|
||||
"AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
|
||||
"global var\n"
|
||||
"AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
|
||||
"bb\n"
|
||||
"AFL_REAL_LD: use this lld linker instead of the compiled in path\n"
|
||||
"\nafl-clang-lto was built with linker target \"%s\" and LTO flags "
|
||||
"\"%s\"\n"
|
||||
@ -796,6 +801,16 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
u8 *ptr2;
|
||||
if (!be_quiet && instrument_mode != INSTRUMENT_LTO &&
|
||||
((ptr2 = getenv("AFL_MAP_SIZE")) || (ptr2 = getenv("AFL_MAPSIZE")))) {
|
||||
|
||||
u32 map_size = atoi(ptr2);
|
||||
if (map_size != MAP_SIZE)
|
||||
FATAL("AFL_MAP_SIZE is not supported by afl-clang-fast");
|
||||
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
|
||||
SAYF(cMGN "[D]" cRST " cd \"%s\";", getthecwd());
|
||||
|
@ -608,20 +608,22 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// save highest location ID to global variable
|
||||
// do this after each function to fail faster
|
||||
if (afl_global_id > MAP_SIZE) {
|
||||
if (!be_quiet && afl_global_id > MAP_SIZE) {
|
||||
|
||||
uint32_t pow2map = 1, map = afl_global_id;
|
||||
while ((map = map >> 1))
|
||||
pow2map++;
|
||||
FATAL(
|
||||
"We have %u blocks to instrument but the map size is only %u! Edit "
|
||||
"config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
|
||||
"afl-fuzz and llvm_mode.",
|
||||
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, 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 "
|
||||
"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 "
|
||||
"target.",
|
||||
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id);
|
||||
|
||||
}
|
||||
|
||||
@ -635,7 +637,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
if (!f) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: init function could not be found (this hould not "
|
||||
"Error: init function could not be found (this should not "
|
||||
"happen)\n");
|
||||
exit(-1);
|
||||
|
||||
|
@ -125,6 +125,7 @@ class AFLCoverage : public ModulePass {
|
||||
std::list<std::string> myWhitelist;
|
||||
uint32_t ngram_size = 0;
|
||||
uint32_t debug = 0;
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
char * ctx_str = NULL;
|
||||
|
||||
};
|
||||
@ -192,6 +193,19 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
/*
|
||||
char *ptr;
|
||||
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
|
||||
|
||||
map_size = atoi(ptr);
|
||||
if (map_size < 8 || map_size > (1 << 29))
|
||||
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30",
|
||||
map_size); if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3);
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* Decide instrumentation ratio */
|
||||
|
||||
char * inst_ratio_str = getenv("AFL_INST_RATIO");
|
||||
@ -365,7 +379,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// if yes we store a context ID for this function in the global var
|
||||
if (has_calls) {
|
||||
|
||||
ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(MAP_SIZE));
|
||||
ConstantInt *NewCtx = ConstantInt::get(Int32Ty, AFL_R(map_size));
|
||||
StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
|
||||
StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
@ -509,7 +523,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
/* Make up cur_loc */
|
||||
|
||||
// cur_loc++;
|
||||
cur_loc = AFL_R(MAP_SIZE);
|
||||
cur_loc = AFL_R(map_size);
|
||||
|
||||
/* There is a problem with Ubuntu 18.04 and llvm 6.0 (see issue #63).
|
||||
The inline function successors() is not inlined and also not found at runtime
|
||||
@ -705,6 +719,56 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
// This is currently disabled because we not only need to create/insert a
|
||||
// function (easy), but also add it as a constructor with an ID < 5
|
||||
|
||||
if (getenv("AFL_LLVM_DONTWRITEID") == NULL) {
|
||||
|
||||
// yes we could create our own function, insert it into ctors ...
|
||||
// but this would be a pain in the butt ... so we use afl-llvm-rt.o
|
||||
|
||||
Function *f = ...
|
||||
|
||||
if (!f) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: init function could not be created (this should not
|
||||
happen)\n"); exit(-1);
|
||||
|
||||
}
|
||||
|
||||
... constructor for f = 4
|
||||
|
||||
BasicBlock *bb = &f->getEntryBlock();
|
||||
if (!bb) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: init function does not have an EntryBlock (this should
|
||||
not happen)\n"); exit(-1);
|
||||
|
||||
}
|
||||
|
||||
BasicBlock::iterator IP = bb->getFirstInsertionPt();
|
||||
IRBuilder<> IRB(&(*IP));
|
||||
|
||||
if (map_size <= 0x800000) {
|
||||
|
||||
GlobalVariable *AFLFinalLoc = new GlobalVariable(
|
||||
M, Int32Ty, true, GlobalValue::ExternalLinkage, 0,
|
||||
"__afl_final_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0,
|
||||
false);
|
||||
ConstantInt *const_loc = ConstantInt::get(Int32Ty, map_size);
|
||||
StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
|
||||
StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* Say something nice. */
|
||||
|
||||
if (!be_quiet) {
|
||||
|
@ -360,11 +360,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
switch (max_size) {
|
||||
|
||||
case 8: IRB.CreateCall(cmplogHookIns1, args, "tmp"); break;
|
||||
case 16: IRB.CreateCall(cmplogHookIns2, args, "tmp"); break;
|
||||
case 32: IRB.CreateCall(cmplogHookIns4, args, "tmp"); break;
|
||||
case 64: IRB.CreateCall(cmplogHookIns8, args, "tmp"); break;
|
||||
default: break;
|
||||
case 8:
|
||||
IRB.CreateCall(cmplogHookIns1, args, "tmp");
|
||||
break;
|
||||
case 16:
|
||||
IRB.CreateCall(cmplogHookIns2, args, "tmp");
|
||||
break;
|
||||
case 32:
|
||||
IRB.CreateCall(cmplogHookIns4, args, "tmp");
|
||||
break;
|
||||
case 64:
|
||||
IRB.CreateCall(cmplogHookIns8, args, "tmp");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -318,10 +318,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
|
||||
CmpInst::Predicate new_pred;
|
||||
switch (pred) {
|
||||
|
||||
case CmpInst::ICMP_UGE: new_pred = CmpInst::ICMP_UGT; break;
|
||||
case CmpInst::ICMP_SGE: new_pred = CmpInst::ICMP_SGT; break;
|
||||
case CmpInst::ICMP_ULE: new_pred = CmpInst::ICMP_ULT; break;
|
||||
case CmpInst::ICMP_SLE: new_pred = CmpInst::ICMP_SLT; break;
|
||||
case CmpInst::ICMP_UGE:
|
||||
new_pred = CmpInst::ICMP_UGT;
|
||||
break;
|
||||
case CmpInst::ICMP_SGE:
|
||||
new_pred = CmpInst::ICMP_SGT;
|
||||
break;
|
||||
case CmpInst::ICMP_ULE:
|
||||
new_pred = CmpInst::ICMP_ULT;
|
||||
break;
|
||||
case CmpInst::ICMP_SLE:
|
||||
new_pred = CmpInst::ICMP_SLT;
|
||||
break;
|
||||
default: // keep the compiler happy
|
||||
continue;
|
||||
|
||||
@ -384,10 +392,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
|
||||
CmpInst::Predicate new_pred;
|
||||
switch (pred) {
|
||||
|
||||
case CmpInst::FCMP_UGE: new_pred = CmpInst::FCMP_UGT; break;
|
||||
case CmpInst::FCMP_OGE: new_pred = CmpInst::FCMP_OGT; break;
|
||||
case CmpInst::FCMP_ULE: new_pred = CmpInst::FCMP_ULT; break;
|
||||
case CmpInst::FCMP_OLE: new_pred = CmpInst::FCMP_OLT; break;
|
||||
case CmpInst::FCMP_UGE:
|
||||
new_pred = CmpInst::FCMP_UGT;
|
||||
break;
|
||||
case CmpInst::FCMP_OGE:
|
||||
new_pred = CmpInst::FCMP_OGT;
|
||||
break;
|
||||
case CmpInst::FCMP_ULE:
|
||||
new_pred = CmpInst::FCMP_ULT;
|
||||
break;
|
||||
case CmpInst::FCMP_OLE:
|
||||
new_pred = CmpInst::FCMP_OLT;
|
||||
break;
|
||||
default: // keep the compiler happy
|
||||
continue;
|
||||
|
||||
@ -855,7 +871,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
icmp_exponent_result =
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
|
||||
break;
|
||||
default: continue;
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -958,7 +975,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
icmp_fraction_result =
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
|
||||
break;
|
||||
default: continue;
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
@ -1004,7 +1022,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
PN->addIncoming(icmp_exponent_result, signequal_bb);
|
||||
PN->addIncoming(icmp_fraction_result, middle_bb);
|
||||
break;
|
||||
default: continue;
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,9 @@ int target_func(char *buf, int size) {
|
||||
}
|
||||
|
||||
break;
|
||||
default: puts("default action"); break;
|
||||
default:
|
||||
puts("default action");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ You can also compile statically-linked binaries by setting STATIC=1. This
|
||||
can be useful when compiling QEMU on a different system than the one you're
|
||||
planning to run the fuzzer on and is most often used with the HOST variable.
|
||||
|
||||
Note: when targetting the i386 architecture, on some bianries the forkserver
|
||||
handshake may fail due to the lack of reversed memory. Fix it with
|
||||
Note: when targetting the i386 architecture, on some binaries the forkserver
|
||||
handshake may fail due to the lack of reserved memory. Fix it with
|
||||
|
||||
export QEMU_RESERVED_VA=0x1000000
|
||||
|
||||
|
@ -23,8 +23,10 @@ in 2.2 and 2.3) have to be set.
|
||||
This address (as well as the RET address, see below) has to be defined in
|
||||
hexadecimal with the 0x prefix or as a decimal value.
|
||||
|
||||
If the target is compiled with position independant code (PIE/PIC), you must
|
||||
add 0x4000000000 to that address, because qemu loads to this base address.
|
||||
*Note:* If the target is compiled with position independant code (PIE/PIC)
|
||||
qemu loads these to a specific base address.
|
||||
For 64 bit you have to add 0x4000000000 (9 zeroes) and for 32 bit 0x40000000
|
||||
(7 zeroes) to the address.
|
||||
On strange setups the base address set by QEMU for PIE executable may change,
|
||||
you can check it printing the process map using
|
||||
`AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace TARGET-BINARY`
|
||||
@ -32,7 +34,7 @@ you can check it printing the process map using
|
||||
If this address is not valid, afl-fuzz will error during startup with the
|
||||
message that the forkserver was not found.
|
||||
|
||||
### 2.2) the RET address
|
||||
### 2.2) The RET address
|
||||
|
||||
The RET address is the last instruction of the persistent loop.
|
||||
The emulator will emit a jump to START when translating the instruction at RET.
|
||||
@ -46,7 +48,7 @@ patch the return address (on stack or in the link register) to return to START
|
||||
It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to
|
||||
be set if the target is position independant.
|
||||
|
||||
### 2.3) the OFFSET
|
||||
### 2.3) The OFFSET
|
||||
|
||||
This option is valid only for x86/x86_64 only, arm/aarch64 do not save the
|
||||
return address on stack.
|
||||
@ -72,7 +74,7 @@ Now to get this value right here some help:
|
||||
8. again print the ESP value
|
||||
9. calculate the difference between the two values - and this is the offset
|
||||
|
||||
### 2.4) resetting the register state
|
||||
### 2.4) Resetting the register state
|
||||
|
||||
It is very, very likely you need to restore the general purpose registers state
|
||||
when starting a new loop. Because of this you 99% of the time should set
|
||||
|
@ -83,6 +83,13 @@ if [ ! -d "/usr/include/glib-2.0/" -a ! -d "/usr/local/include/glib-2.0/" ]; the
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -d "/usr/include/pixman-1/" -a ! -d "/usr/local/include/pixman-1/" ]; then
|
||||
|
||||
echo "[-] Error: devel version of 'pixman-1' not found, please install first."
|
||||
PREREQ_NOTFOUND=1
|
||||
|
||||
fi
|
||||
|
||||
if echo "$CC" | grep -qF /afl-; then
|
||||
|
||||
echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool."
|
||||
@ -230,10 +237,12 @@ if [ "$ORIG_CPU_TARGET" = "" ]; then
|
||||
|
||||
make >/dev/null || exit 1
|
||||
|
||||
gcc test-instr.c -o test-instr || exit 1
|
||||
cc test-instr.c -o test-instr || exit 1
|
||||
|
||||
unset AFL_INST_RATIO
|
||||
export ASAN_OPTIONS=detect_leaks=0
|
||||
|
||||
echo "[*] Comparing two afl-showmap -Q outputs..."
|
||||
echo 0 | ./afl-showmap -m none -Q -q -o .test-instr0 ./test-instr || exit 1
|
||||
echo 1 | ./afl-showmap -m none -Q -q -o .test-instr1 ./test-instr || exit 1
|
||||
|
||||
|
@ -51,9 +51,11 @@ int main() {
|
||||
|
||||
switch (z) {
|
||||
|
||||
case 0xBEEF: break;
|
||||
case 0xBEEF:
|
||||
break;
|
||||
|
||||
default: return 4;
|
||||
default:
|
||||
return 4;
|
||||
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ static void __compcov_trace(u64 cur_loc, const u8 *v0, const u8 *v1, size_t n) {
|
||||
if (debug_fd != 1) {
|
||||
|
||||
char debugbuf[4096];
|
||||
snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %lu\n", cur_loc,
|
||||
snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %zu\n", cur_loc,
|
||||
v0 == NULL ? "(null)" : (char *)v0,
|
||||
v1 == NULL ? "(null)" : (char *)v1, n);
|
||||
write(debug_fd, debugbuf, strlen(debugbuf));
|
||||
|
@ -294,7 +294,7 @@ static void print_mappings(void) {
|
||||
void afl_forkserver(CPUState *cpu) {
|
||||
|
||||
u32 map_size = 0;
|
||||
static unsigned char tmp[4] = {0, 0, 0, 0};
|
||||
unsigned char tmp[4] = {0};
|
||||
|
||||
if (forkserver_installed == 1) return;
|
||||
forkserver_installed = 1;
|
||||
|
@ -55,11 +55,20 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2,
|
||||
|
||||
switch (ot & MO_SIZE) {
|
||||
|
||||
case MO_64: gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2); break;
|
||||
case MO_32: gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2); break;
|
||||
case MO_16: gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2); break;
|
||||
case MO_8: gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2); break;
|
||||
default: break;
|
||||
case MO_64:
|
||||
gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
case MO_32:
|
||||
gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
case MO_16:
|
||||
gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
case MO_8:
|
||||
gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -78,10 +87,17 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2,
|
||||
|
||||
switch (ot & MO_SIZE) {
|
||||
|
||||
case MO_64: gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2); break;
|
||||
case MO_32: gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2); break;
|
||||
case MO_16: gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2); break;
|
||||
default: break;
|
||||
case MO_64:
|
||||
gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
case MO_32:
|
||||
gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
case MO_16:
|
||||
gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,10 @@ all: $(TARGETS)
|
||||
@if [ "$(AFL_NO_X86)" != "" ]; then echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."; fi
|
||||
|
||||
unsigaction32.so:
|
||||
@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
|
||||
@if $(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
|
||||
|
||||
unsigaction64.so:
|
||||
$(CC) -m64 -fPIC -shared unsigaction.c -o unsigaction64.so
|
||||
@if $(CC) -m64 -fPIC -shared unsigaction.c -o unsigaction64.so 2>/dev/null ; then echo "unsigaction64 build success"; else echo "unsigaction64 build failure (that's fine)"; fi
|
||||
|
||||
clean:
|
||||
rm -f unsigaction32.so unsigaction64.so
|
||||
|
@ -84,6 +84,7 @@ static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
|
||||
static u8 *target_path;
|
||||
static u8 qemu_mode;
|
||||
static u32 map_size = MAP_SIZE;
|
||||
|
||||
/* Constants used for describing byte behavior. */
|
||||
|
||||
@ -115,13 +116,13 @@ static u8 count_class_lookup[256] = {
|
||||
|
||||
static void classify_counts(u8 *mem) {
|
||||
|
||||
u32 i = MAP_SIZE;
|
||||
u32 i = map_size;
|
||||
|
||||
if (edges_only) {
|
||||
|
||||
while (i--) {
|
||||
|
||||
if (*mem) *mem = 1;
|
||||
if (*mem) { *mem = 1; }
|
||||
mem++;
|
||||
|
||||
}
|
||||
@ -144,10 +145,13 @@ static void classify_counts(u8 *mem) {
|
||||
static inline u8 anything_set(void) {
|
||||
|
||||
u32 *ptr = (u32 *)trace_bits;
|
||||
u32 i = (MAP_SIZE >> 2);
|
||||
u32 i = (map_size >> 2);
|
||||
|
||||
while (i--)
|
||||
if (*(ptr++)) return 1;
|
||||
while (i--) {
|
||||
|
||||
if (*(ptr++)) { return 1; }
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -168,13 +172,16 @@ static void read_initial_file(void) {
|
||||
struct stat st;
|
||||
s32 fd = open(in_file, O_RDONLY);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", in_file);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", in_file); }
|
||||
|
||||
if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file.");
|
||||
if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); }
|
||||
|
||||
if (st.st_size >= TMIN_MAX_FILE) {
|
||||
|
||||
if (st.st_size >= TMIN_MAX_FILE)
|
||||
FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
|
||||
|
||||
}
|
||||
|
||||
in_len = st.st_size;
|
||||
in_data = ck_alloc_nozero(in_len);
|
||||
|
||||
@ -196,7 +203,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
|
||||
|
||||
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
if (ret < 0) PFATAL("Unable to create '%s'", path);
|
||||
if (ret < 0) { PFATAL("Unable to create '%s'", path); }
|
||||
|
||||
ck_write(ret, mem, len, path);
|
||||
|
||||
@ -217,14 +224,14 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
|
||||
s32 prog_in_fd;
|
||||
u32 cksum;
|
||||
|
||||
memset(trace_bits, 0, MAP_SIZE);
|
||||
memset(trace_bits, 0, map_size);
|
||||
MEM_BARRIER();
|
||||
|
||||
prog_in_fd = write_to_file(prog_in, mem, len);
|
||||
|
||||
child_pid = fork();
|
||||
|
||||
if (child_pid < 0) PFATAL("fork() failed");
|
||||
if (child_pid < 0) { PFATAL("fork() failed"); }
|
||||
|
||||
if (!child_pid) {
|
||||
|
||||
@ -277,7 +284,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
|
||||
|
||||
setitimer(ITIMER_REAL, &it, NULL);
|
||||
|
||||
if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed");
|
||||
if (waitpid(child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
|
||||
|
||||
child_pid = 0;
|
||||
it.it_value.tv_sec = 0;
|
||||
@ -289,9 +296,12 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
|
||||
|
||||
/* Clean up bitmap, analyze exit condition, etc. */
|
||||
|
||||
if (*(u32 *)trace_bits == EXEC_FAIL_SIG)
|
||||
if (*(u32 *)trace_bits == EXEC_FAIL_SIG) {
|
||||
|
||||
FATAL("Unable to execute '%s'", argv[0]);
|
||||
|
||||
}
|
||||
|
||||
classify_counts(trace_bits);
|
||||
total_execs++;
|
||||
|
||||
@ -311,7 +321,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
|
||||
|
||||
}
|
||||
|
||||
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
|
||||
cksum = hash32(trace_bits, map_size, HASH_CONST);
|
||||
|
||||
/* We don't actually care if the target is crashing or not,
|
||||
except that when it does, the checksum should be different. */
|
||||
@ -324,7 +334,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
|
||||
|
||||
}
|
||||
|
||||
if (first_run) orig_cksum = cksum;
|
||||
if (first_run) { orig_cksum = cksum; }
|
||||
|
||||
return cksum;
|
||||
|
||||
@ -339,9 +349,12 @@ static void show_char(u8 val) {
|
||||
switch (val) {
|
||||
|
||||
case 0 ... 32:
|
||||
case 127 ... 255: SAYF("#%02x", val); break;
|
||||
case 127 ... 255:
|
||||
SAYF("#%02x", val);
|
||||
break;
|
||||
|
||||
default: SAYF(" %c ", val);
|
||||
default:
|
||||
SAYF(" %c ", val);
|
||||
|
||||
}
|
||||
|
||||
@ -386,7 +399,12 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
|
||||
|
||||
while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) {
|
||||
|
||||
if (rtype < (b_data[i + rlen] & 0x0f)) rtype = b_data[i + rlen] & 0x0f;
|
||||
if (rtype < (b_data[i + rlen] & 0x0f)) {
|
||||
|
||||
rtype = b_data[i + rlen] & 0x0f;
|
||||
|
||||
}
|
||||
|
||||
rlen++;
|
||||
|
||||
}
|
||||
@ -453,9 +471,11 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
case 5 ... MAX_AUTO_EXTRA - 1: break;
|
||||
case 5 ... MAX_AUTO_EXTRA - 1:
|
||||
break;
|
||||
|
||||
default: rtype = RESP_SUSPECT;
|
||||
default:
|
||||
rtype = RESP_SUSPECT;
|
||||
|
||||
}
|
||||
|
||||
@ -471,36 +491,60 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
|
||||
|
||||
if (!((i + off) % 16)) {
|
||||
|
||||
if (off) SAYF(cRST cLCY ">");
|
||||
if (off) { SAYF(cRST cLCY ">"); }
|
||||
|
||||
if (use_hex_offsets) {
|
||||
|
||||
if (use_hex_offsets)
|
||||
SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (rtype) {
|
||||
|
||||
case RESP_NONE: SAYF(cLGR bgGRA); break;
|
||||
case RESP_MINOR: SAYF(cBRI bgGRA); break;
|
||||
case RESP_VARIABLE: SAYF(cBLK bgCYA); break;
|
||||
case RESP_FIXED: SAYF(cBLK bgMGN); break;
|
||||
case RESP_LEN: SAYF(cBLK bgLGN); break;
|
||||
case RESP_CKSUM: SAYF(cBLK bgYEL); break;
|
||||
case RESP_SUSPECT: SAYF(cBLK bgLRD); break;
|
||||
case RESP_NONE:
|
||||
SAYF(cLGR bgGRA);
|
||||
break;
|
||||
case RESP_MINOR:
|
||||
SAYF(cBRI bgGRA);
|
||||
break;
|
||||
case RESP_VARIABLE:
|
||||
SAYF(cBLK bgCYA);
|
||||
break;
|
||||
case RESP_FIXED:
|
||||
SAYF(cBLK bgMGN);
|
||||
break;
|
||||
case RESP_LEN:
|
||||
SAYF(cBLK bgLGN);
|
||||
break;
|
||||
case RESP_CKSUM:
|
||||
SAYF(cBLK bgYEL);
|
||||
break;
|
||||
case RESP_SUSPECT:
|
||||
SAYF(cBLK bgLRD);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
show_char(in_data[i + off]);
|
||||
|
||||
if (off != rlen - 1 && (i + off + 1) % 16)
|
||||
if (off != rlen - 1 && (i + off + 1) % 16) {
|
||||
|
||||
SAYF(" ");
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
SAYF(cRST " ");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (use_hex_offsets)
|
||||
@ -510,13 +554,27 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
|
||||
|
||||
switch (rtype) {
|
||||
|
||||
case RESP_NONE: SAYF("no-op block\n"); break;
|
||||
case RESP_MINOR: SAYF("superficial content\n"); break;
|
||||
case RESP_VARIABLE: SAYF("critical stream\n"); break;
|
||||
case RESP_FIXED: SAYF("\"magic value\" section\n"); break;
|
||||
case RESP_LEN: SAYF("suspected length field\n"); break;
|
||||
case RESP_CKSUM: SAYF("suspected cksum or magic int\n"); break;
|
||||
case RESP_SUSPECT: SAYF("suspected checksummed block\n"); break;
|
||||
case RESP_NONE:
|
||||
SAYF("no-op block\n");
|
||||
break;
|
||||
case RESP_MINOR:
|
||||
SAYF("superficial content\n");
|
||||
break;
|
||||
case RESP_VARIABLE:
|
||||
SAYF("critical stream\n");
|
||||
break;
|
||||
case RESP_FIXED:
|
||||
SAYF("\"magic value\" section\n");
|
||||
break;
|
||||
case RESP_LEN:
|
||||
SAYF("suspected length field\n");
|
||||
break;
|
||||
case RESP_CKSUM:
|
||||
SAYF("suspected cksum or magic int\n");
|
||||
break;
|
||||
case RESP_SUSPECT:
|
||||
SAYF("suspected checksummed block\n");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -593,16 +651,21 @@ static void analyze(char **argv) {
|
||||
|
||||
b_data[i] = RESP_FIXED;
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
b_data[i] = RESP_VARIABLE;
|
||||
|
||||
}
|
||||
|
||||
/* When all checksums change, flip most significant bit of b_data. */
|
||||
|
||||
if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 &&
|
||||
prev_a10 != add_10)
|
||||
prev_a10 != add_10) {
|
||||
|
||||
seq_byte ^= 0x80;
|
||||
|
||||
}
|
||||
|
||||
b_data[i] |= seq_byte;
|
||||
|
||||
prev_xff = xor_ff;
|
||||
@ -619,10 +682,13 @@ static void analyze(char **argv) {
|
||||
OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.",
|
||||
100.0 - ((double)boring_len * 100) / in_len);
|
||||
|
||||
if (exec_hangs)
|
||||
if (exec_hangs) {
|
||||
|
||||
WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST,
|
||||
exec_hangs);
|
||||
|
||||
}
|
||||
|
||||
ck_free(b_data);
|
||||
|
||||
}
|
||||
@ -633,7 +699,7 @@ static void handle_stop_sig(int sig) {
|
||||
|
||||
stop_soon = 1;
|
||||
|
||||
if (child_pid > 0) kill(child_pid, SIGKILL);
|
||||
if (child_pid > 0) { kill(child_pid, SIGKILL); }
|
||||
|
||||
}
|
||||
|
||||
@ -644,7 +710,7 @@ static void set_up_environment(void) {
|
||||
u8 *x;
|
||||
|
||||
dev_null_fd = open("/dev/null", O_RDWR);
|
||||
if (dev_null_fd < 0) PFATAL("Unable to open /dev/null");
|
||||
if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||
|
||||
if (!prog_in) {
|
||||
|
||||
@ -653,7 +719,7 @@ static void set_up_environment(void) {
|
||||
if (access(use_dir, R_OK | W_OK | X_OK)) {
|
||||
|
||||
use_dir = get_afl_env("TMPDIR");
|
||||
if (!use_dir) use_dir = "/tmp";
|
||||
if (!use_dir) { use_dir = "/tmp"; }
|
||||
|
||||
}
|
||||
|
||||
@ -667,27 +733,39 @@ static void set_up_environment(void) {
|
||||
|
||||
if (x) {
|
||||
|
||||
if (!strstr(x, "abort_on_error=1"))
|
||||
if (!strstr(x, "abort_on_error=1")) {
|
||||
|
||||
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
|
||||
|
||||
if (!strstr(x, "symbolize=0"))
|
||||
}
|
||||
|
||||
if (!strstr(x, "symbolize=0")) {
|
||||
|
||||
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
x = get_afl_env("MSAN_OPTIONS");
|
||||
|
||||
if (x) {
|
||||
|
||||
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR)))
|
||||
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
|
||||
|
||||
FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
|
||||
MSAN_ERROR) " - please fix!");
|
||||
|
||||
if (!strstr(x, "symbolize=0"))
|
||||
}
|
||||
|
||||
if (!strstr(x, "symbolize=0")) {
|
||||
|
||||
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setenv("ASAN_OPTIONS",
|
||||
"abort_on_error=1:"
|
||||
"detect_leaks=0:"
|
||||
@ -712,20 +790,28 @@ static void set_up_environment(void) {
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
if (afl_preload[i] == ',') {
|
||||
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
}
|
||||
|
||||
if (qemu_preload) {
|
||||
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
qemu_preload, afl_preload, afl_preload);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
afl_preload, afl_preload);
|
||||
|
||||
}
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
@ -795,8 +881,10 @@ static void usage(u8 *argv0) {
|
||||
" (must contain abort_on_error=1 and symbolize=0)\n"
|
||||
"MSAN_OPTIONS: custom settings for MSAN\n"
|
||||
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
|
||||
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
|
||||
"AFL_ANALYZE_HEX: print file offsets in hexadecimal instead of decimal\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_SKIP_BIN_CHECK: skip checking the location of and the target\n"
|
||||
|
||||
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
|
||||
@ -817,26 +905,26 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n");
|
||||
|
||||
while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0)
|
||||
while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'i':
|
||||
|
||||
if (in_file) FATAL("Multiple -i options not supported");
|
||||
if (in_file) { FATAL("Multiple -i options not supported"); }
|
||||
in_file = optarg;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
if (prog_in) FATAL("Multiple -f options not supported");
|
||||
if (prog_in) { FATAL("Multiple -f options not supported"); }
|
||||
use_stdin = 0;
|
||||
prog_in = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
|
||||
if (edges_only) FATAL("Multiple -e options not supported");
|
||||
if (edges_only) { FATAL("Multiple -e options not supported"); }
|
||||
edges_only = 1;
|
||||
break;
|
||||
|
||||
@ -844,7 +932,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
u8 suffix = 'M';
|
||||
|
||||
if (mem_limit_given) FATAL("Multiple -m options not supported");
|
||||
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
|
||||
mem_limit_given = 1;
|
||||
|
||||
if (!optarg) { FATAL("Wrong usage of -m"); }
|
||||
@ -857,66 +945,83 @@ int main(int argc, char **argv, char **envp) {
|
||||
}
|
||||
|
||||
if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
|
||||
optarg[0] == '-')
|
||||
optarg[0] == '-') {
|
||||
|
||||
FATAL("Bad syntax used for -m");
|
||||
|
||||
switch (suffix) {
|
||||
|
||||
case 'T': mem_limit *= 1024 * 1024; break;
|
||||
case 'G': mem_limit *= 1024; break;
|
||||
case 'k': mem_limit /= 1024; break;
|
||||
case 'M': break;
|
||||
|
||||
default: FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (mem_limit < 5) FATAL("Dangerously low value of -m");
|
||||
switch (suffix) {
|
||||
|
||||
case 'T':
|
||||
mem_limit *= 1024 * 1024;
|
||||
break;
|
||||
case 'G':
|
||||
mem_limit *= 1024;
|
||||
break;
|
||||
case 'k':
|
||||
mem_limit /= 1024;
|
||||
break;
|
||||
case 'M':
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (mem_limit < 5) { FATAL("Dangerously low value of -m"); }
|
||||
|
||||
if (sizeof(rlim_t) == 4 && mem_limit > 2000) {
|
||||
|
||||
if (sizeof(rlim_t) == 4 && mem_limit > 2000)
|
||||
FATAL("Value of -m out of range on 32-bit systems");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
if (timeout_given) FATAL("Multiple -t options not supported");
|
||||
if (timeout_given) { FATAL("Multiple -t options not supported"); }
|
||||
timeout_given = 1;
|
||||
|
||||
if (!optarg) FATAL("Wrong usage of -t");
|
||||
if (!optarg) { FATAL("Wrong usage of -t"); }
|
||||
|
||||
exec_tmout = atoi(optarg);
|
||||
|
||||
if (exec_tmout < 10 || optarg[0] == '-')
|
||||
if (exec_tmout < 10 || optarg[0] == '-') {
|
||||
|
||||
FATAL("Dangerously low value of -t");
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
|
||||
if (qemu_mode) FATAL("Multiple -Q options not supported");
|
||||
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
|
||||
if (qemu_mode) { FATAL("Multiple -Q options not supported"); }
|
||||
if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; }
|
||||
|
||||
qemu_mode = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
|
||||
if (unicorn_mode) FATAL("Multiple -U options not supported");
|
||||
if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN;
|
||||
if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
|
||||
if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; }
|
||||
|
||||
unicorn_mode = 1;
|
||||
break;
|
||||
|
||||
case 'W': /* Wine+QEMU mode */
|
||||
|
||||
if (use_wine) FATAL("Multiple -W options not supported");
|
||||
if (use_wine) { FATAL("Multiple -W options not supported"); }
|
||||
qemu_mode = 1;
|
||||
use_wine = 1;
|
||||
|
||||
if (!mem_limit_given) mem_limit = 0;
|
||||
if (!mem_limit_given) { mem_limit = 0; }
|
||||
|
||||
break;
|
||||
|
||||
@ -925,18 +1030,23 @@ int main(int argc, char **argv, char **envp) {
|
||||
return -1;
|
||||
break;
|
||||
|
||||
default: usage(argv[0]);
|
||||
default:
|
||||
usage(argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc || !in_file) usage(argv[0]);
|
||||
}
|
||||
|
||||
if (optind == argc || !in_file) { usage(argv[0]); }
|
||||
|
||||
map_size = get_map_size();
|
||||
|
||||
use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX");
|
||||
|
||||
check_environment_vars(envp);
|
||||
|
||||
sharedmem_t shm = {0};
|
||||
trace_bits = afl_shm_init(&shm, MAP_SIZE, 0);
|
||||
trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||
atexit(at_exit_handler);
|
||||
setup_signal_handlers();
|
||||
|
||||
@ -947,17 +1057,24 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
if (qemu_mode) {
|
||||
|
||||
if (use_wine)
|
||||
if (use_wine) {
|
||||
|
||||
use_argv =
|
||||
get_wine_argv(argv[0], &target_path, argc - optind, argv + optind);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
use_argv =
|
||||
get_qemu_argv(argv[0], &target_path, argc - optind, argv + optind);
|
||||
|
||||
} else
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
use_argv = argv + optind;
|
||||
|
||||
}
|
||||
|
||||
SAYF("\n");
|
||||
|
||||
read_initial_file();
|
||||
@ -967,17 +1084,23 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
analyze_run_target(use_argv, in_data, in_len, 1);
|
||||
|
||||
if (child_timed_out)
|
||||
if (child_timed_out) {
|
||||
|
||||
FATAL("Target binary times out (adjusting -t may help).");
|
||||
|
||||
if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set())
|
||||
}
|
||||
|
||||
if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) {
|
||||
|
||||
FATAL("No instrumentation detected.");
|
||||
|
||||
}
|
||||
|
||||
analyze(use_argv);
|
||||
|
||||
OKF("We're done here. Have a nice day!\n");
|
||||
|
||||
if (target_path) ck_free(target_path);
|
||||
if (target_path) { ck_free(target_path); }
|
||||
|
||||
afl_shm_deinit(&shm);
|
||||
|
||||
|
110
src/afl-as.c
110
src/afl-as.c
@ -126,9 +126,9 @@ static void edit_params(int argc, char **argv) {
|
||||
is not set. We need to check these non-standard variables to properly
|
||||
handle the pass_thru logic later on. */
|
||||
|
||||
if (!tmp_dir) tmp_dir = getenv("TEMP");
|
||||
if (!tmp_dir) tmp_dir = getenv("TMP");
|
||||
if (!tmp_dir) tmp_dir = "/tmp";
|
||||
if (!tmp_dir) { tmp_dir = getenv("TEMP"); }
|
||||
if (!tmp_dir) { tmp_dir = getenv("TMP"); }
|
||||
if (!tmp_dir) { tmp_dir = "/tmp"; }
|
||||
|
||||
as_params = ck_alloc((argc + 32) * sizeof(u8 *));
|
||||
|
||||
@ -138,11 +138,16 @@ static void edit_params(int argc, char **argv) {
|
||||
|
||||
for (i = 1; i < argc - 1; i++) {
|
||||
|
||||
if (!strcmp(argv[i], "--64"))
|
||||
if (!strcmp(argv[i], "--64")) {
|
||||
|
||||
use_64bit = 1;
|
||||
else if (!strcmp(argv[i], "--32"))
|
||||
|
||||
} else if (!strcmp(argv[i], "--32")) {
|
||||
|
||||
use_64bit = 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* The Apple case is a bit different... */
|
||||
@ -195,11 +200,16 @@ static void edit_params(int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (input_file[1])
|
||||
if (input_file[1]) {
|
||||
|
||||
FATAL("Incorrect use (not called through afl-gcc?)");
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
input_file = NULL;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Check if this looks like a standard invocation as a part of an attempt
|
||||
@ -210,13 +220,18 @@ static void edit_params(int argc, char **argv) {
|
||||
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
|
||||
strncmp(input_file, "/var/tmp/", 9) &&
|
||||
strncmp(input_file, "/tmp/", 5) &&
|
||||
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL)
|
||||
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) {
|
||||
|
||||
pass_thru = 1;
|
||||
else if (getenv("AFL_AS_FORCE_INSTRUMENT"))
|
||||
|
||||
} else if (getenv("AFL_AS_FORCE_INSTRUMENT")) {
|
||||
|
||||
unsetenv("AFL_AS_FORCE_INSTRUMENT");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
modified_file =
|
||||
alloc_printf("%s/.afl-%u-%u.s", tmp_dir, getpid(), (u32)time(NULL));
|
||||
|
||||
@ -251,19 +266,21 @@ static void add_instrumentation(void) {
|
||||
if (input_file) {
|
||||
|
||||
inf = fopen(input_file, "r");
|
||||
if (!inf) PFATAL("Unable to read '%s'", input_file);
|
||||
if (!inf) { PFATAL("Unable to read '%s'", input_file); }
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
inf = stdin;
|
||||
|
||||
}
|
||||
|
||||
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);
|
||||
|
||||
if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);
|
||||
if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); }
|
||||
|
||||
outf = fdopen(outfd, "w");
|
||||
|
||||
if (!outf) PFATAL("fdopen() failed");
|
||||
if (!outf) { PFATAL("fdopen() failed"); }
|
||||
|
||||
while (fgets(line, MAX_LINE, inf)) {
|
||||
|
||||
@ -287,7 +304,7 @@ static void add_instrumentation(void) {
|
||||
|
||||
fputs(line, outf);
|
||||
|
||||
if (pass_thru) continue;
|
||||
if (pass_thru) { continue; }
|
||||
|
||||
/* All right, this is where the actual fun begins. For one, we only want to
|
||||
instrument the .text section. So, let's keep track of that in processed
|
||||
@ -300,9 +317,12 @@ static void add_instrumentation(void) {
|
||||
around them, so we use that as a signal. */
|
||||
|
||||
if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
|
||||
isdigit(line[10]) && line[11] == '\n')
|
||||
isdigit(line[10]) && line[11] == '\n') {
|
||||
|
||||
skip_next_label = 1;
|
||||
|
||||
}
|
||||
|
||||
if (!strncmp(line + 2, "text\n", 5) ||
|
||||
!strncmp(line + 2, "section\t.text", 13) ||
|
||||
!strncmp(line + 2, "section\t__TEXT,__text", 21) ||
|
||||
@ -330,23 +350,23 @@ static void add_instrumentation(void) {
|
||||
|
||||
if (strstr(line, ".code")) {
|
||||
|
||||
if (strstr(line, ".code32")) skip_csect = use_64bit;
|
||||
if (strstr(line, ".code64")) skip_csect = !use_64bit;
|
||||
if (strstr(line, ".code32")) { skip_csect = use_64bit; }
|
||||
if (strstr(line, ".code64")) { skip_csect = !use_64bit; }
|
||||
|
||||
}
|
||||
|
||||
/* Detect syntax changes, as could happen with hand-written assembly.
|
||||
Skip Intel blocks, resume instrumentation when back to AT&T. */
|
||||
|
||||
if (strstr(line, ".intel_syntax")) skip_intel = 1;
|
||||
if (strstr(line, ".att_syntax")) skip_intel = 0;
|
||||
if (strstr(line, ".intel_syntax")) { skip_intel = 1; }
|
||||
if (strstr(line, ".att_syntax")) { skip_intel = 0; }
|
||||
|
||||
/* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
|
||||
|
||||
if (line[0] == '#' || line[1] == '#') {
|
||||
|
||||
if (strstr(line, "#APP")) skip_app = 1;
|
||||
if (strstr(line, "#NO_APP")) skip_app = 0;
|
||||
if (strstr(line, "#APP")) { skip_app = 1; }
|
||||
if (strstr(line, "#NO_APP")) { skip_app = 0; }
|
||||
|
||||
}
|
||||
|
||||
@ -375,9 +395,12 @@ static void add_instrumentation(void) {
|
||||
*/
|
||||
|
||||
if (skip_intel || skip_app || skip_csect || !instr_ok || line[0] == '#' ||
|
||||
line[0] == ' ')
|
||||
line[0] == ' ') {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Conditional branch instruction (jnz, etc). We append the instrumentation
|
||||
right after the branch (to instrument the not-taken path) and at the
|
||||
branch destination label (handled later on). */
|
||||
@ -449,13 +472,18 @@ static void add_instrumentation(void) {
|
||||
.Lfunc_begin0-style exception handling calculations (a problem on
|
||||
MacOS X). */
|
||||
|
||||
if (!skip_next_label)
|
||||
if (!skip_next_label) {
|
||||
|
||||
instrument_next = 1;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
skip_next_label = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Function label (always instrumented, deferred mode). */
|
||||
@ -468,17 +496,19 @@ static void add_instrumentation(void) {
|
||||
|
||||
}
|
||||
|
||||
if (ins_lines) fputs(use_64bit ? main_payload_64 : main_payload_32, outf);
|
||||
if (ins_lines) { fputs(use_64bit ? main_payload_64 : main_payload_32, outf); }
|
||||
|
||||
if (input_file) fclose(inf);
|
||||
if (input_file) { fclose(inf); }
|
||||
fclose(outf);
|
||||
|
||||
if (!be_quiet) {
|
||||
|
||||
if (!ins_lines)
|
||||
if (!ins_lines) {
|
||||
|
||||
WARNF("No instrumentation targets found%s.",
|
||||
pass_thru ? " (pass-thru mode)" : "");
|
||||
else {
|
||||
|
||||
} else {
|
||||
|
||||
char modeline[100];
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s",
|
||||
@ -514,10 +544,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n");
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
}
|
||||
|
||||
if (argc < 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) {
|
||||
|
||||
fprintf(
|
||||
@ -565,14 +597,20 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (inst_ratio_str) {
|
||||
|
||||
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100)
|
||||
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) {
|
||||
|
||||
FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");
|
||||
|
||||
}
|
||||
|
||||
if (getenv(AS_LOOP_ENV_VAR))
|
||||
}
|
||||
|
||||
if (getenv(AS_LOOP_ENV_VAR)) {
|
||||
|
||||
FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");
|
||||
|
||||
}
|
||||
|
||||
setenv(AS_LOOP_ENV_VAR, "1", 1);
|
||||
|
||||
/* When compiling with ASAN, we don't have a particularly elegant way to skip
|
||||
@ -582,11 +620,11 @@ int main(int argc, char **argv) {
|
||||
if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) {
|
||||
|
||||
sanitizer = 1;
|
||||
if (!getenv("AFL_INST_RATIO")) inst_ratio /= 3;
|
||||
if (!getenv("AFL_INST_RATIO")) { inst_ratio /= 3; }
|
||||
|
||||
}
|
||||
|
||||
if (!just_version) add_instrumentation();
|
||||
if (!just_version) { add_instrumentation(); }
|
||||
|
||||
if (!(pid = fork())) {
|
||||
|
||||
@ -595,11 +633,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (pid < 0) PFATAL("fork() failed");
|
||||
if (pid < 0) { PFATAL("fork() failed"); }
|
||||
|
||||
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
|
||||
if (waitpid(pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); }
|
||||
|
||||
if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file);
|
||||
if (!getenv("AFL_KEEP_ASSEMBLY")) { unlink(modified_file); }
|
||||
|
||||
exit(WEXITSTATUS(status));
|
||||
|
||||
|
@ -70,9 +70,9 @@ char *afl_environment_variables[] = {
|
||||
"AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO",
|
||||
"AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID",
|
||||
"AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN",
|
||||
"AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI",
|
||||
"AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
|
||||
"AFL_NO_X86", // not really an env but we dont want to warn on it
|
||||
"AFL_PATH", "AFL_PERFORMANCE_FILE",
|
||||
"AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
|
||||
//"AFL_PERSISTENT", // not implemented anymore, so warn additionally
|
||||
"AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV",
|
||||
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
|
||||
@ -101,7 +101,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
|
||||
|
||||
if (aa_loc) {
|
||||
|
||||
if (!prog_in) FATAL("@@ syntax is not supported by this tool.");
|
||||
if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
|
||||
|
||||
*use_stdin = 0;
|
||||
|
||||
@ -198,7 +198,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
cp = alloc_printf("%s/afl-qemu-trace", tmp);
|
||||
|
||||
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp);
|
||||
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
|
||||
|
||||
*target_path_p = new_argv[0] = cp;
|
||||
return new_argv;
|
||||
@ -222,13 +222,15 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
ck_free(own_copy);
|
||||
|
||||
}
|
||||
|
||||
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
|
||||
|
||||
if (cp) ck_free(cp);
|
||||
if (cp) { ck_free(cp); }
|
||||
*target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace");
|
||||
|
||||
return new_argv;
|
||||
@ -275,13 +277,13 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
cp = alloc_printf("%s/afl-qemu-trace", tmp);
|
||||
|
||||
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp);
|
||||
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
|
||||
|
||||
ck_free(cp);
|
||||
|
||||
cp = alloc_printf("%s/afl-wine-trace", tmp);
|
||||
|
||||
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp);
|
||||
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
|
||||
|
||||
*target_path_p = new_argv[0] = cp;
|
||||
return new_argv;
|
||||
@ -374,9 +376,13 @@ u8 *find_binary(u8 *fname) {
|
||||
target_path = ck_strdup(fname);
|
||||
|
||||
if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
|
||||
!(st.st_mode & 0111) || st.st_size < 4)
|
||||
!(st.st_mode & 0111) || st.st_size < 4) {
|
||||
|
||||
free(target_path);
|
||||
FATAL("Program '%s' not found or not executable", fname);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
while (env_path) {
|
||||
@ -389,29 +395,43 @@ u8 *find_binary(u8 *fname) {
|
||||
memcpy(cur_elem, env_path, delim - env_path);
|
||||
delim++;
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
cur_elem = ck_strdup(env_path);
|
||||
|
||||
}
|
||||
|
||||
env_path = delim;
|
||||
|
||||
if (cur_elem[0])
|
||||
if (cur_elem[0]) {
|
||||
|
||||
target_path = alloc_printf("%s/%s", cur_elem, fname);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
target_path = ck_strdup(fname);
|
||||
|
||||
}
|
||||
|
||||
ck_free(cur_elem);
|
||||
|
||||
if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
|
||||
(st.st_mode & 0111) && st.st_size >= 4)
|
||||
(st.st_mode & 0111) && st.st_size >= 4) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
ck_free(target_path);
|
||||
target_path = NULL;
|
||||
|
||||
}
|
||||
|
||||
if (!target_path) FATAL("Program '%s' not found or not executable", fname);
|
||||
if (!target_path) {
|
||||
|
||||
FATAL("Program '%s' not found or not executable", fname);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -421,7 +441,7 @@ u8 *find_binary(u8 *fname) {
|
||||
|
||||
void check_environment_vars(char **envp) {
|
||||
|
||||
if (be_quiet) return;
|
||||
if (be_quiet) { return; }
|
||||
|
||||
int index = 0, found = 0;
|
||||
char *env, *val;
|
||||
@ -435,24 +455,30 @@ void check_environment_vars(char **envp) {
|
||||
} else if (strncmp(env, "AFL_", 4) == 0) {
|
||||
|
||||
int i = 0, match = 0;
|
||||
while (match == 0 && afl_environment_variables[i] != NULL)
|
||||
while (match == 0 && afl_environment_variables[i] != NULL) {
|
||||
|
||||
if (strncmp(env, afl_environment_variables[i],
|
||||
strlen(afl_environment_variables[i])) == 0 &&
|
||||
env[strlen(afl_environment_variables[i])] == '=') {
|
||||
|
||||
match = 1;
|
||||
if ((val = getenv(afl_environment_variables[i])) && !*val)
|
||||
if ((val = getenv(afl_environment_variables[i])) && !*val) {
|
||||
|
||||
WARNF(
|
||||
"AFL environment variable %s defined but is empty, this can "
|
||||
"lead to unexpected consequences",
|
||||
afl_environment_variables[i]);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (match == 0) {
|
||||
|
||||
WARNF("Mistyped AFL environment variable: %s", env);
|
||||
@ -464,7 +490,7 @@ void check_environment_vars(char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (found) sleep(2);
|
||||
if (found) { sleep(2); }
|
||||
|
||||
}
|
||||
|
||||
@ -472,10 +498,16 @@ char *get_afl_env(char *env) {
|
||||
|
||||
char *val;
|
||||
|
||||
if ((val = getenv(env)) != NULL)
|
||||
if (!be_quiet)
|
||||
if ((val = getenv(env)) != NULL) {
|
||||
|
||||
if (!be_quiet) {
|
||||
|
||||
OKF("Loaded environment variable %s with value %s", env, val);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
}
|
||||
@ -486,7 +518,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
|
||||
|
||||
s32 fd = open(fname, O_RDONLY);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", fname);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
|
||||
|
||||
ck_read(fd, map, len, fname);
|
||||
|
||||
@ -885,3 +917,25 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms,
|
||||
|
||||
}
|
||||
|
||||
u32 get_map_size() {
|
||||
|
||||
uint32_t map_size = MAP_SIZE;
|
||||
char * ptr;
|
||||
|
||||
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
|
||||
|
||||
map_size = atoi(ptr);
|
||||
if (map_size < 8 || map_size > (1 << 29)) {
|
||||
|
||||
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size);
|
||||
|
||||
}
|
||||
|
||||
if (map_size % 8) { map_size = (((map_size >> 3) + 1) << 3); }
|
||||
|
||||
}
|
||||
|
||||
return map_size;
|
||||
|
||||
}
|
||||
|
||||
|
@ -128,12 +128,16 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
unsigned char tmp[4] = {0, 0, 0, 0};
|
||||
pid_t child_pid = -1;
|
||||
|
||||
if (!be_quiet) ACTF("Using Fauxserver:");
|
||||
if (!be_quiet) { ACTF("Using Fauxserver:"); }
|
||||
|
||||
/* 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) abort(); // TODO: Abort?
|
||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) {
|
||||
|
||||
abort(); // TODO: Abort?
|
||||
|
||||
}
|
||||
|
||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
||||
|
||||
@ -144,13 +148,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
/* Wait for parent by reading from the pipe. Exit if read fails. */
|
||||
|
||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(0);
|
||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) { exit(0); }
|
||||
|
||||
/* Create a clone of our process. */
|
||||
|
||||
child_pid = fork();
|
||||
|
||||
if (child_pid < 0) PFATAL("Fork failed");
|
||||
if (child_pid < 0) { PFATAL("Fork failed"); }
|
||||
|
||||
/* In child process: close fds, resume execution. */
|
||||
|
||||
@ -177,7 +181,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
/* In parent process: write PID to AFL. */
|
||||
|
||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(0);
|
||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { exit(0); }
|
||||
|
||||
/* after child exited, get and relay exit status to parent through waitpid.
|
||||
*/
|
||||
@ -191,7 +195,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
/* Relay wait status to AFL pipe, then loop back. */
|
||||
|
||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(0);
|
||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
|
||||
|
||||
}
|
||||
|
||||
@ -212,25 +216,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
int status;
|
||||
s32 rlen;
|
||||
|
||||
if (!be_quiet) ACTF("Spinning up the fork server...");
|
||||
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
|
||||
|
||||
if (fsrv->use_fauxsrv) {
|
||||
|
||||
/* TODO: Come up with sone nice way to initalize this all */
|
||||
|
||||
if (fsrv->init_child_func != fsrv_exec_child)
|
||||
if (fsrv->init_child_func != fsrv_exec_child) {
|
||||
|
||||
FATAL("Different forkserver not compatible with fauxserver");
|
||||
|
||||
}
|
||||
|
||||
fsrv->init_child_func = afl_fauxsrv_execv;
|
||||
|
||||
}
|
||||
|
||||
if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed");
|
||||
if (pipe(st_pipe) || pipe(ctl_pipe)) { PFATAL("pipe() failed"); }
|
||||
|
||||
fsrv->last_run_timed_out = 0;
|
||||
fsrv->fsrv_pid = fork();
|
||||
|
||||
if (fsrv->fsrv_pid < 0) PFATAL("fork() failed");
|
||||
if (fsrv->fsrv_pid < 0) { PFATAL("fork() failed"); }
|
||||
|
||||
if (!fsrv->fsrv_pid) {
|
||||
|
||||
@ -295,8 +302,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
/* Set up control and status pipes, close the unneeded original fds. */
|
||||
|
||||
if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed");
|
||||
if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
|
||||
if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) { PFATAL("dup2() failed"); }
|
||||
if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) { PFATAL("dup2() failed"); }
|
||||
|
||||
close(ctl_pipe[0]);
|
||||
close(ctl_pipe[1]);
|
||||
@ -308,12 +315,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
close(fsrv->dev_urandom_fd);
|
||||
#endif
|
||||
if (fsrv->plot_file != NULL) fclose(fsrv->plot_file);
|
||||
if (fsrv->plot_file != NULL) { fclose(fsrv->plot_file); }
|
||||
|
||||
/* This should improve performance a bit, since it stops the linker from
|
||||
doing extra work post-fork(). */
|
||||
|
||||
if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0);
|
||||
if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); }
|
||||
|
||||
/* Set sane defaults for ASAN if nothing else specified. */
|
||||
|
||||
@ -391,37 +398,49 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
if (rlen == 4) {
|
||||
|
||||
if (!be_quiet) OKF("All right - fork server is up.");
|
||||
if (!be_quiet) { OKF("All right - fork server is up."); }
|
||||
|
||||
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
||||
|
||||
if (!be_quiet && getenv("AFL_DEBUG"))
|
||||
if (!be_quiet && getenv("AFL_DEBUG")) {
|
||||
|
||||
ACTF("Extended forkserver functions received (%08x).", status);
|
||||
|
||||
}
|
||||
|
||||
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
|
||||
|
||||
fsrv->snapshot = 1;
|
||||
if (!be_quiet) ACTF("Using SNAPSHOT feature.");
|
||||
if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
|
||||
|
||||
}
|
||||
|
||||
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
||||
|
||||
fsrv->map_size = FS_OPT_GET_MAPSIZE(status);
|
||||
if (unlikely(fsrv->map_size % 8)) {
|
||||
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
||||
|
||||
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
||||
|
||||
if (unlikely(tmp_map_size % 8)) {
|
||||
|
||||
// should not happen
|
||||
WARNF("Target reported non-aligned map size of %ud", fsrv->map_size);
|
||||
fsrv->map_size = (((fsrv->map_size + 8) >> 3) << 3);
|
||||
WARNF("Target reported non-aligned map size of %ud", tmp_map_size);
|
||||
tmp_map_size = (((tmp_map_size + 8) >> 3) << 3);
|
||||
|
||||
}
|
||||
|
||||
if (!be_quiet) ACTF("Target map size: %u", fsrv->map_size);
|
||||
if (fsrv->map_size > MAP_SIZE)
|
||||
if (!be_quiet) { ACTF("Target map size: %u", tmp_map_size); }
|
||||
if (tmp_map_size > fsrv->map_size) {
|
||||
|
||||
FATAL(
|
||||
"Target's coverage map size of %u is larger than the one this "
|
||||
"afl++ is compiled with (%u) (change MAP_SIZE and recompile)\n",
|
||||
fsrv->map_size, MAP_SIZE);
|
||||
"afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and "
|
||||
"recompile or set AFL_MAP_SIZE)\n",
|
||||
tmp_map_size, fsrv->map_size);
|
||||
|
||||
}
|
||||
|
||||
fsrv->map_size = tmp_map_size;
|
||||
|
||||
}
|
||||
|
||||
@ -431,27 +450,44 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
// this is not afl-fuzz - we deny and return
|
||||
status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT));
|
||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4)
|
||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||
|
||||
FATAL("Writing to forkserver failed.");
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (!be_quiet) ACTF("Using AUTODICT feature.");
|
||||
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
|
||||
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4)
|
||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||
|
||||
FATAL("Writing to forkserver failed.");
|
||||
if (read(fsrv->fsrv_st_fd, &status, 4) != 4)
|
||||
|
||||
}
|
||||
|
||||
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
|
||||
|
||||
FATAL("Reading from forkserver failed.");
|
||||
|
||||
if (status < 2 || (u32)status > 0xffffff)
|
||||
}
|
||||
|
||||
if (status < 2 || (u32)status > 0xffffff) {
|
||||
|
||||
FATAL("Dictionary has an illegal size: %d", status);
|
||||
|
||||
}
|
||||
|
||||
u32 len = status, offset = 0, count = 0;
|
||||
u8 *dict = ck_alloc(len);
|
||||
if (dict == NULL)
|
||||
if (dict == NULL) {
|
||||
|
||||
FATAL("Could not allocate %u bytes of autodictionary memory", len);
|
||||
|
||||
}
|
||||
|
||||
while (len != 0) {
|
||||
|
||||
rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
|
||||
@ -481,7 +517,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
if (!be_quiet) ACTF("Loaded %u autodictionary entries", count);
|
||||
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
||||
ck_free(dict);
|
||||
|
||||
}
|
||||
@ -492,10 +528,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->last_run_timed_out)
|
||||
if (fsrv->last_run_timed_out) {
|
||||
|
||||
FATAL("Timeout while initializing fork server (adjusting -t may help)");
|
||||
|
||||
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed");
|
||||
}
|
||||
|
||||
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); }
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
|
||||
@ -575,9 +614,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG)
|
||||
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) {
|
||||
|
||||
FATAL("Unable to execute target application ('%s')", argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->mem_limit && fsrv->mem_limit < 500 && fsrv->uses_asan) {
|
||||
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
@ -646,7 +688,7 @@ 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, SIGKILL); }
|
||||
if (fsrv->fsrv_pid > 0) {
|
||||
|
||||
kill(fsrv->fsrv_pid, SIGKILL);
|
||||
@ -675,7 +717,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); }
|
||||
|
||||
} else {
|
||||
|
||||
@ -687,7 +729,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
|
||||
|
||||
if (!fsrv->out_file) {
|
||||
|
||||
if (ftruncate(fd, len)) PFATAL("ftruncate() failed");
|
||||
if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
} else {
|
||||
@ -722,7 +764,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) {
|
||||
|
||||
if (*stop_soon_p) return 0;
|
||||
if (*stop_soon_p) { return 0; }
|
||||
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
|
||||
|
||||
}
|
||||
@ -731,12 +773,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
|
||||
|
||||
if (*stop_soon_p) return 0;
|
||||
if (*stop_soon_p) { return 0; }
|
||||
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
|
||||
if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); }
|
||||
|
||||
exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p);
|
||||
|
||||
@ -747,13 +789,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
kill(fsrv->child_pid, SIGKILL);
|
||||
fsrv->last_run_timed_out = 1;
|
||||
if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
|
||||
if (read(fsrv->fsrv_st_fd, &status, 4) < 4) { exec_ms = 0; }
|
||||
|
||||
}
|
||||
|
||||
if (!exec_ms) {
|
||||
|
||||
if (*stop_soon_p) return 0;
|
||||
if (*stop_soon_p) { return 0; }
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
"Unable to communicate with fork server. Some possible reasons:\n\n"
|
||||
" - You've run out of memory. Use -m to increase the the memory "
|
||||
@ -779,7 +821,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
}
|
||||
|
||||
if (!WIFSTOPPED(status)) fsrv->child_pid = 0;
|
||||
if (!WIFSTOPPED(status)) { fsrv->child_pid = 0; }
|
||||
|
||||
fsrv->total_execs++;
|
||||
|
||||
@ -795,9 +837,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
fsrv->last_kill_signal = WTERMSIG(status);
|
||||
|
||||
if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL)
|
||||
if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) {
|
||||
|
||||
return FSRV_RUN_TMOUT;
|
||||
|
||||
}
|
||||
|
||||
return FSRV_RUN_CRASH;
|
||||
|
||||
}
|
||||
|
@ -35,15 +35,15 @@ void write_bitmap(afl_state_t *afl) {
|
||||
u8 fname[PATH_MAX];
|
||||
s32 fd;
|
||||
|
||||
if (!afl->bitmap_changed) return;
|
||||
if (!afl->bitmap_changed) { return; }
|
||||
afl->bitmap_changed = 0;
|
||||
|
||||
snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
|
||||
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", fname);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
|
||||
|
||||
ck_write(fd, afl->virgin_bits, MAP_SIZE, fname);
|
||||
ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname);
|
||||
|
||||
close(fd);
|
||||
|
||||
@ -102,11 +102,16 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
|
||||
(cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) ||
|
||||
(cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) ||
|
||||
(cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) ||
|
||||
(cur[7] && vir[7] == 0xff))
|
||||
(cur[7] && vir[7] == 0xff)) {
|
||||
|
||||
ret = 2;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
ret = 1;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) ||
|
||||
@ -129,9 +134,12 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(ret) && likely(virgin_map == afl->virgin_bits))
|
||||
if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) {
|
||||
|
||||
afl->bitmap_changed = 1;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -145,8 +153,6 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
|
||||
u32 i = (afl->fsrv.map_size >> 2);
|
||||
u32 ret = 0;
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
u32 v = *(ptr++);
|
||||
@ -181,17 +187,15 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
|
||||
u32 i = (afl->fsrv.map_size >> 2);
|
||||
u32 ret = 0;
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
u32 v = *(ptr++);
|
||||
|
||||
if (!v) continue;
|
||||
if (v & 0x000000ff) ++ret;
|
||||
if (v & 0x0000ff00) ++ret;
|
||||
if (v & 0x00ff0000) ++ret;
|
||||
if (v & 0xff000000) ++ret;
|
||||
if (!v) { continue; }
|
||||
if (v & 0x000000ff) { ++ret; }
|
||||
if (v & 0x0000ff00) { ++ret; }
|
||||
if (v & 0x00ff0000) { ++ret; }
|
||||
if (v & 0xff000000) { ++ret; }
|
||||
|
||||
}
|
||||
|
||||
@ -208,8 +212,6 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
|
||||
u32 i = (afl->fsrv.map_size >> 2);
|
||||
u32 ret = 0;
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
u32 v = *(ptr++);
|
||||
@ -217,11 +219,11 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
|
||||
/* This is called on the virgin bitmap, so optimize for the most likely
|
||||
case. */
|
||||
|
||||
if (v == 0xffffffff) continue;
|
||||
if ((v & 0x000000ff) != 0x000000ff) ++ret;
|
||||
if ((v & 0x0000ff00) != 0x0000ff00) ++ret;
|
||||
if ((v & 0x00ff0000) != 0x00ff0000) ++ret;
|
||||
if ((v & 0xff000000) != 0xff000000) ++ret;
|
||||
if (v == 0xffffffff) { continue; }
|
||||
if ((v & 0x000000ff) != 0x000000ff) { ++ret; }
|
||||
if ((v & 0x0000ff00) != 0x0000ff00) { ++ret; }
|
||||
if ((v & 0x00ff0000) != 0x00ff0000) { ++ret; }
|
||||
if ((v & 0xff000000) != 0xff000000) { ++ret; }
|
||||
|
||||
}
|
||||
|
||||
@ -246,8 +248,6 @@ void simplify_trace(afl_state_t *afl, u64 *mem) {
|
||||
|
||||
u32 i = (afl->fsrv.map_size >> 3);
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
@ -265,10 +265,12 @@ void simplify_trace(afl_state_t *afl, u64 *mem) {
|
||||
mem8[6] = simplify_lookup[mem8[6]];
|
||||
mem8[7] = simplify_lookup[mem8[7]];
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
*mem = 0x0101010101010101ULL;
|
||||
|
||||
}
|
||||
|
||||
++mem;
|
||||
|
||||
}
|
||||
@ -281,8 +283,6 @@ void simplify_trace(afl_state_t *afl, u32 *mem) {
|
||||
|
||||
u32 i = (afl->fsrv.map_size >> 2);
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
@ -332,11 +332,17 @@ void init_count_class16(void) {
|
||||
|
||||
u32 b1, b2;
|
||||
|
||||
for (b1 = 0; b1 < 256; b1++)
|
||||
for (b2 = 0; b2 < 256; b2++)
|
||||
for (b1 = 0; b1 < 256; b1++) {
|
||||
|
||||
for (b2 = 0; b2 < 256; b2++) {
|
||||
|
||||
count_class_lookup16[(b1 << 8) + b2] =
|
||||
(count_class_lookup8[b1] << 8) | count_class_lookup8[b2];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef WORD_SIZE_64
|
||||
@ -347,8 +353,6 @@ void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
u32 i = (fsrv->map_size >> 3);
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
@ -378,8 +382,6 @@ void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
u32 i = (fsrv->map_size >> 2);
|
||||
|
||||
if (i == 0) i = 1;
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
@ -411,7 +413,7 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
|
||||
|
||||
while (i < afl->fsrv.map_size) {
|
||||
|
||||
if (*(src++)) dst[i >> 3] |= 1 << (i & 7);
|
||||
if (*(src++)) { dst[i >> 3] |= 1 << (i & 7); }
|
||||
++i;
|
||||
|
||||
}
|
||||
@ -437,27 +439,35 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
|
||||
|
||||
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
|
||||
|
||||
if (afl->splicing_with >= 0)
|
||||
if (afl->splicing_with >= 0) {
|
||||
|
||||
sprintf(ret + strlen(ret), "+%06d", afl->splicing_with);
|
||||
|
||||
}
|
||||
|
||||
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
|
||||
|
||||
if (afl->stage_cur_byte >= 0) {
|
||||
|
||||
sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
|
||||
|
||||
if (afl->stage_val_type != STAGE_VAL_NONE)
|
||||
if (afl->stage_val_type != STAGE_VAL_NONE) {
|
||||
|
||||
sprintf(ret + strlen(ret), ",val:%s%+d",
|
||||
(afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
|
||||
afl->stage_cur_val);
|
||||
|
||||
} else
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
|
||||
|
||||
}
|
||||
|
||||
if (hnb == 2) strcat(ret, ",+cov");
|
||||
}
|
||||
|
||||
if (hnb == 2) { strcat(ret, ",+cov"); }
|
||||
|
||||
return ret;
|
||||
|
||||
@ -481,7 +491,7 @@ static void write_crash_readme(afl_state_t *afl) {
|
||||
|
||||
/* Do not die on errors here - that would be impolite. */
|
||||
|
||||
if (unlikely(fd < 0)) return;
|
||||
if (unlikely(fd < 0)) { return; }
|
||||
|
||||
f = fdopen(fd, "w");
|
||||
|
||||
@ -526,7 +536,7 @@ static void write_crash_readme(afl_state_t *afl) {
|
||||
|
||||
u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
if (unlikely(len == 0)) return 0;
|
||||
if (unlikely(len == 0)) { return 0; }
|
||||
|
||||
u8 *queue_fn = "";
|
||||
u8 hnb = '\0';
|
||||
@ -559,7 +569,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
|
||||
|
||||
if (unlikely(afl->crash_mode)) ++afl->total_crashes;
|
||||
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -592,11 +602,14 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
|
||||
|
||||
if (unlikely(res == FSRV_RUN_ERROR))
|
||||
if (unlikely(res == FSRV_RUN_ERROR)) {
|
||||
|
||||
FATAL("Unable to execute target application");
|
||||
|
||||
}
|
||||
|
||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn);
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
|
||||
ck_write(fd, mem, len, queue_fn);
|
||||
close(fd);
|
||||
|
||||
@ -615,7 +628,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
++afl->total_tmouts;
|
||||
|
||||
if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping;
|
||||
if (afl->unique_hangs >= KEEP_UNIQUE_HANG) { return keeping; }
|
||||
|
||||
if (likely(!afl->dumb_mode)) {
|
||||
|
||||
@ -625,7 +638,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
simplify_trace(afl, (u32 *)afl->fsrv.trace_bits);
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
if (!has_new_bits(afl, afl->virgin_tmout)) return keeping;
|
||||
if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; }
|
||||
|
||||
}
|
||||
|
||||
@ -645,9 +658,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
timeout actually uncovers a crash. Make sure we don't discard it if
|
||||
so. */
|
||||
|
||||
if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) goto keep_as_crash;
|
||||
if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) {
|
||||
|
||||
if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) return keeping;
|
||||
goto keep_as_crash;
|
||||
|
||||
}
|
||||
|
||||
if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) { return keeping; }
|
||||
|
||||
}
|
||||
|
||||
@ -679,7 +696,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
++afl->total_crashes;
|
||||
|
||||
if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping;
|
||||
if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) { return keeping; }
|
||||
|
||||
if (likely(!afl->dumb_mode)) {
|
||||
|
||||
@ -689,11 +706,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
simplify_trace(afl, (u32 *)afl->fsrv.trace_bits);
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
if (!has_new_bits(afl, afl->virgin_crash)) return keeping;
|
||||
if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; }
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(!afl->unique_crashes)) write_crash_readme(afl);
|
||||
if (unlikely(!afl->unique_crashes)) { write_crash_readme(afl); }
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
@ -729,9 +746,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
break;
|
||||
|
||||
case FSRV_RUN_ERROR: FATAL("Unable to execute target application");
|
||||
case FSRV_RUN_ERROR:
|
||||
FATAL("Unable to execute target application");
|
||||
|
||||
default: return keeping;
|
||||
default:
|
||||
return keeping;
|
||||
|
||||
}
|
||||
|
||||
@ -739,7 +758,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
test case, too. */
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
|
||||
ck_write(fd, mem, len, fn);
|
||||
close(fd);
|
||||
|
||||
|
@ -37,9 +37,12 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
|
||||
|
||||
if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary)
|
||||
if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) {
|
||||
|
||||
argv[0] = fsrv->cmplog_binary;
|
||||
|
||||
}
|
||||
|
||||
execv(argv[0], argv);
|
||||
|
||||
}
|
||||
@ -54,7 +57,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
size_t post_len =
|
||||
afl->post_handler(afl->post_data, out_buf, len, &post_buf);
|
||||
if (!post_buf || !post_len) return 0;
|
||||
if (!post_buf || !post_len) { return 0; }
|
||||
out_buf = post_buf;
|
||||
len = post_len;
|
||||
|
||||
@ -64,7 +67,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) return 1;
|
||||
if (afl->stop_soon) { return 1; }
|
||||
|
||||
if (fault == FSRV_RUN_TMOUT) {
|
||||
|
||||
@ -75,10 +78,12 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
afl->subseq_tmouts = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Users can hit us with SIGUSR1 to request the current input
|
||||
to be abandoned. */
|
||||
|
||||
|
@ -59,7 +59,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
f = fopen(fname, "r");
|
||||
|
||||
if (!f) PFATAL("Unable to open '%s'", fname);
|
||||
if (!f) { PFATAL("Unable to open '%s'", fname); }
|
||||
|
||||
while ((lptr = fgets(buf, MAX_LINE, f))) {
|
||||
|
||||
@ -70,57 +70,79 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
/* Trim on left and right. */
|
||||
|
||||
while (isspace(*lptr))
|
||||
while (isspace(*lptr)) {
|
||||
|
||||
++lptr;
|
||||
|
||||
}
|
||||
|
||||
rptr = lptr + strlen(lptr) - 1;
|
||||
while (rptr >= lptr && isspace(*rptr))
|
||||
while (rptr >= lptr && isspace(*rptr)) {
|
||||
|
||||
--rptr;
|
||||
|
||||
}
|
||||
|
||||
++rptr;
|
||||
*rptr = 0;
|
||||
|
||||
/* Skip empty lines and comments. */
|
||||
|
||||
if (!*lptr || *lptr == '#') continue;
|
||||
if (!*lptr || *lptr == '#') { continue; }
|
||||
|
||||
/* All other lines must end with '"', which we can consume. */
|
||||
|
||||
--rptr;
|
||||
|
||||
if (rptr < lptr || *rptr != '"')
|
||||
if (rptr < lptr || *rptr != '"') {
|
||||
|
||||
FATAL("Malformed name=\"value\" pair in line %u.", cur_line);
|
||||
|
||||
}
|
||||
|
||||
*rptr = 0;
|
||||
|
||||
/* Skip alphanumerics and dashes (label). */
|
||||
|
||||
while (isalnum(*lptr) || *lptr == '_')
|
||||
while (isalnum(*lptr) || *lptr == '_') {
|
||||
|
||||
++lptr;
|
||||
|
||||
}
|
||||
|
||||
/* If @number follows, parse that. */
|
||||
|
||||
if (*lptr == '@') {
|
||||
|
||||
++lptr;
|
||||
if (atoi(lptr) > dict_level) continue;
|
||||
while (isdigit(*lptr))
|
||||
if (atoi(lptr) > dict_level) { continue; }
|
||||
while (isdigit(*lptr)) {
|
||||
|
||||
++lptr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Skip whitespace and = signs. */
|
||||
|
||||
while (isspace(*lptr) || *lptr == '=')
|
||||
while (isspace(*lptr) || *lptr == '=') {
|
||||
|
||||
++lptr;
|
||||
|
||||
}
|
||||
|
||||
/* Consume opening '"'. */
|
||||
|
||||
if (*lptr != '"')
|
||||
if (*lptr != '"') {
|
||||
|
||||
FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line);
|
||||
|
||||
}
|
||||
|
||||
++lptr;
|
||||
|
||||
if (!*lptr) FATAL("Empty keyword in line %u.", cur_line);
|
||||
if (!*lptr) { FATAL("Empty keyword in line %u.", cur_line); }
|
||||
|
||||
/* Okay, let's allocate memory and copy data between "...", handling
|
||||
\xNN escaping, \\, and \". */
|
||||
@ -130,7 +152,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr);
|
||||
|
||||
if (!wptr) PFATAL("no mem for data");
|
||||
if (!wptr) { PFATAL("no mem for data"); }
|
||||
|
||||
while (*lptr) {
|
||||
|
||||
@ -154,9 +176,12 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
}
|
||||
|
||||
if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2]))
|
||||
if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) {
|
||||
|
||||
FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line);
|
||||
|
||||
}
|
||||
|
||||
*(wptr++) = ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) |
|
||||
(strchr(hexdigits, tolower(lptr[2])) - hexdigits);
|
||||
|
||||
@ -165,7 +190,9 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
break;
|
||||
|
||||
default: *(wptr++) = *(lptr++); ++klen;
|
||||
default:
|
||||
*(wptr++) = *(lptr++);
|
||||
++klen;
|
||||
|
||||
}
|
||||
|
||||
@ -173,14 +200,17 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
|
||||
|
||||
afl->extras[afl->extras_cnt].len = klen;
|
||||
|
||||
if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE)
|
||||
if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) {
|
||||
|
||||
FATAL(
|
||||
"Keyword too big in line %u (%s, limit is %s)", cur_line,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
|
||||
if (*min_len > klen) *min_len = klen;
|
||||
if (*max_len < klen) *max_len = klen;
|
||||
}
|
||||
|
||||
if (*min_len > klen) { *min_len = klen; }
|
||||
if (*max_len < klen) { *max_len = klen; }
|
||||
|
||||
++afl->extras_cnt;
|
||||
|
||||
@ -227,7 +257,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
|
||||
}
|
||||
|
||||
if (x) FATAL("Dictionary levels not supported for directories.");
|
||||
if (x) { FATAL("Dictionary levels not supported for directories."); }
|
||||
|
||||
while ((de = readdir(d))) {
|
||||
|
||||
@ -235,7 +265,11 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
u8 * fn = alloc_printf("%s/%s", dir, de->d_name);
|
||||
s32 fd;
|
||||
|
||||
if (lstat(fn, &st) || access(fn, R_OK)) PFATAL("Unable to access '%s'", fn);
|
||||
if (lstat(fn, &st) || access(fn, R_OK)) {
|
||||
|
||||
PFATAL("Unable to access '%s'", fn);
|
||||
|
||||
}
|
||||
|
||||
/* This also takes care of . and .. */
|
||||
if (!S_ISREG(st.st_mode) || !st.st_size) {
|
||||
@ -245,14 +279,17 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
|
||||
}
|
||||
|
||||
if (st.st_size > MAX_DICT_FILE)
|
||||
if (st.st_size > MAX_DICT_FILE) {
|
||||
|
||||
FATAL(
|
||||
"Extra '%s' is too big (%s, limit is %s)", fn,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
|
||||
if (min_len > st.st_size) min_len = st.st_size;
|
||||
if (max_len < st.st_size) max_len = st.st_size;
|
||||
}
|
||||
|
||||
if (min_len > st.st_size) { min_len = st.st_size; }
|
||||
if (max_len < st.st_size) { max_len = st.st_size; }
|
||||
|
||||
afl->extras = ck_realloc_block(
|
||||
afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data));
|
||||
@ -262,7 +299,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
|
||||
fd = open(fn, O_RDONLY);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
|
||||
|
||||
ck_read(fd, afl->extras[afl->extras_cnt].data, st.st_size, fn);
|
||||
|
||||
@ -277,7 +314,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
|
||||
check_and_sort:
|
||||
|
||||
if (!afl->extras_cnt) FATAL("No usable files in '%s'", dir);
|
||||
if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); }
|
||||
|
||||
qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
|
||||
compare_extras_len);
|
||||
@ -286,22 +323,32 @@ check_and_sort:
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
|
||||
|
||||
if (max_len > 32)
|
||||
if (max_len > 32) {
|
||||
|
||||
WARNF("Some tokens are relatively large (%s) - consider trimming.",
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
|
||||
|
||||
if (afl->extras_cnt > MAX_DET_EXTRAS)
|
||||
}
|
||||
|
||||
if (afl->extras_cnt > MAX_DET_EXTRAS) {
|
||||
|
||||
WARNF("More than %d tokens - will use them probabilistically.",
|
||||
MAX_DET_EXTRAS);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Helper function for maybe_add_auto(afl, ) */
|
||||
|
||||
static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
|
||||
|
||||
while (len--)
|
||||
if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1;
|
||||
while (len--) {
|
||||
|
||||
if (tolower(*(m1++)) ^ tolower(*(m2++))) { return 1; }
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -318,14 +365,17 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
|
||||
|
||||
/* Allow users to specify that they don't want auto dictionaries. */
|
||||
|
||||
if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return;
|
||||
if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) { return; }
|
||||
|
||||
/* Skip runs of identical bytes. */
|
||||
|
||||
for (i = 1; i < len; ++i)
|
||||
if (mem[0] ^ mem[i]) break;
|
||||
for (i = 1; i < len; ++i) {
|
||||
|
||||
if (i == len) return;
|
||||
if (mem[0] ^ mem[i]) { break; }
|
||||
|
||||
}
|
||||
|
||||
if (i == len) { return; }
|
||||
|
||||
/* Reject builtin interesting values. */
|
||||
|
||||
@ -333,33 +383,51 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
|
||||
|
||||
i = sizeof(interesting_16) >> 1;
|
||||
|
||||
while (i--)
|
||||
while (i--) {
|
||||
|
||||
if (*((u16 *)mem) == interesting_16[i] ||
|
||||
*((u16 *)mem) == SWAP16(interesting_16[i]))
|
||||
*((u16 *)mem) == SWAP16(interesting_16[i])) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (len == 4) {
|
||||
|
||||
i = sizeof(interesting_32) >> 2;
|
||||
|
||||
while (i--)
|
||||
while (i--) {
|
||||
|
||||
if (*((u32 *)mem) == interesting_32[i] ||
|
||||
*((u32 *)mem) == SWAP32(interesting_32[i]))
|
||||
*((u32 *)mem) == SWAP32(interesting_32[i])) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Reject anything that matches existing extras. Do a case-insensitive
|
||||
match. We optimize by exploiting the fact that extras[] are sorted
|
||||
by size. */
|
||||
|
||||
for (i = 0; i < afl->extras_cnt; ++i)
|
||||
if (afl->extras[i].len >= len) break;
|
||||
for (i = 0; i < afl->extras_cnt; ++i) {
|
||||
|
||||
for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i)
|
||||
if (!memcmp_nocase(afl->extras[i].data, mem, len)) return;
|
||||
if (afl->extras[i].len >= len) { break; }
|
||||
|
||||
}
|
||||
|
||||
for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i) {
|
||||
|
||||
if (!memcmp_nocase(afl->extras[i].data, mem, len)) { return; }
|
||||
|
||||
}
|
||||
|
||||
/* Last but not least, check afl->a_extras[] for matches. There are no
|
||||
guarantees of a particular sort order. */
|
||||
@ -423,7 +491,7 @@ void save_auto(afl_state_t *afl) {
|
||||
|
||||
u32 i;
|
||||
|
||||
if (!afl->auto_changed) return;
|
||||
if (!afl->auto_changed) { return; }
|
||||
afl->auto_changed = 0;
|
||||
|
||||
for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
|
||||
@ -434,7 +502,7 @@ void save_auto(afl_state_t *afl) {
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
|
||||
ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn);
|
||||
|
||||
@ -461,7 +529,7 @@ void load_auto(afl_state_t *afl) {
|
||||
|
||||
if (fd < 0) {
|
||||
|
||||
if (errno != ENOENT) PFATAL("Unable to open '%s'", fn);
|
||||
if (errno != ENOENT) { PFATAL("Unable to open '%s'", fn); }
|
||||
ck_free(fn);
|
||||
break;
|
||||
|
||||
@ -472,21 +540,29 @@ void load_auto(afl_state_t *afl) {
|
||||
|
||||
len = read(fd, tmp, MAX_AUTO_EXTRA + 1);
|
||||
|
||||
if (len < 0) PFATAL("Unable to read from '%s'", fn);
|
||||
if (len < 0) { PFATAL("Unable to read from '%s'", fn); }
|
||||
|
||||
if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) {
|
||||
|
||||
if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA)
|
||||
maybe_add_auto((u8 *)afl, tmp, len);
|
||||
|
||||
}
|
||||
|
||||
close(fd);
|
||||
ck_free(fn);
|
||||
|
||||
}
|
||||
|
||||
if (i)
|
||||
if (i) {
|
||||
|
||||
OKF("Loaded %u auto-discovered dictionary tokens.", i);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
OKF("No auto-generated dictionary tokens to reuse.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Destroy extras. */
|
||||
@ -495,14 +571,20 @@ void destroy_extras(afl_state_t *afl) {
|
||||
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < afl->extras_cnt; ++i)
|
||||
for (i = 0; i < afl->extras_cnt; ++i) {
|
||||
|
||||
ck_free(afl->extras[i].data);
|
||||
|
||||
}
|
||||
|
||||
ck_free(afl->extras);
|
||||
|
||||
for (i = 0; i < afl->a_extras_cnt; ++i)
|
||||
for (i = 0; i < afl->a_extras_cnt; ++i) {
|
||||
|
||||
ck_free(afl->a_extras[i].data);
|
||||
|
||||
}
|
||||
|
||||
ck_free(afl->a_extras);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,12 +35,15 @@ void setup_custom_mutator(afl_state_t *afl) {
|
||||
|
||||
if (fn) {
|
||||
|
||||
if (afl->limit_time_sig)
|
||||
if (afl->limit_time_sig) {
|
||||
|
||||
FATAL(
|
||||
"MOpt and custom mutator are mutually exclusive. We accept pull "
|
||||
"requests that integrates MOpt with the optional mutators "
|
||||
"(custom/radamsa/redquenn/...).");
|
||||
|
||||
}
|
||||
|
||||
load_custom_mutator(afl, fn);
|
||||
|
||||
return;
|
||||
@ -53,19 +56,26 @@ void setup_custom_mutator(afl_state_t *afl) {
|
||||
|
||||
if (module_name) {
|
||||
|
||||
if (afl->limit_time_sig)
|
||||
if (afl->limit_time_sig) {
|
||||
|
||||
FATAL(
|
||||
"MOpt and Python mutator are mutually exclusive. We accept pull "
|
||||
"requests that integrates MOpt with the optional mutators "
|
||||
"(custom/radamsa/redqueen/...).");
|
||||
|
||||
}
|
||||
|
||||
load_custom_mutator_py(afl, module_name);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
if (afl->afl_env.afl_python_module)
|
||||
if (afl->afl_env.afl_python_module) {
|
||||
|
||||
FATAL("Your AFL binary was built without Python support");
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -76,7 +86,7 @@ void destroy_custom_mutator(afl_state_t *afl) {
|
||||
|
||||
afl->mutator->afl_custom_deinit(afl->mutator->data);
|
||||
|
||||
if (afl->mutator->dh) dlclose(afl->mutator->dh);
|
||||
if (afl->mutator->dh) { dlclose(afl->mutator->dh); }
|
||||
|
||||
if (afl->mutator->pre_save_buf) {
|
||||
|
||||
@ -104,20 +114,26 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
ACTF("Loading custom mutator library from '%s'...", fn);
|
||||
|
||||
dh = dlopen(fn, RTLD_NOW);
|
||||
if (!dh) FATAL("%s", dlerror());
|
||||
if (!dh) { FATAL("%s", dlerror()); }
|
||||
afl->mutator->dh = dh;
|
||||
|
||||
/* Mutator */
|
||||
/* "afl_custom_init", required */
|
||||
afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
|
||||
if (!afl->mutator->afl_custom_init)
|
||||
if (!afl->mutator->afl_custom_init) {
|
||||
|
||||
FATAL("Symbol 'afl_custom_init' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_deinit", required */
|
||||
afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
|
||||
if (!afl->mutator->afl_custom_deinit)
|
||||
if (!afl->mutator->afl_custom_deinit) {
|
||||
|
||||
FATAL("Symbol 'afl_custom_deinit' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
|
||||
afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
|
||||
if (!afl->mutator->afl_custom_fuzz) {
|
||||
@ -126,32 +142,47 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
|
||||
|
||||
afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
|
||||
if (!afl->mutator->afl_custom_fuzz)
|
||||
if (!afl->mutator->afl_custom_fuzz) {
|
||||
|
||||
FATAL("Symbol 'afl_custom_mutator' not found.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_pre_save", optional */
|
||||
afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
|
||||
if (!afl->mutator->afl_custom_pre_save)
|
||||
if (!afl->mutator->afl_custom_pre_save) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_pre_save' not found.");
|
||||
|
||||
}
|
||||
|
||||
u8 notrim = 0;
|
||||
/* "afl_custom_init_trim", optional */
|
||||
afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
|
||||
if (!afl->mutator->afl_custom_init_trim)
|
||||
if (!afl->mutator->afl_custom_init_trim) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_init_trim' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_trim", optional */
|
||||
afl->mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
|
||||
if (!afl->mutator->afl_custom_trim)
|
||||
if (!afl->mutator->afl_custom_trim) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_trim' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_post_trim", optional */
|
||||
afl->mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
|
||||
if (!afl->mutator->afl_custom_post_trim)
|
||||
if (!afl->mutator->afl_custom_post_trim) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_post_trim' not found.");
|
||||
|
||||
}
|
||||
|
||||
if (notrim) {
|
||||
|
||||
afl->mutator->afl_custom_init_trim = NULL;
|
||||
@ -166,33 +197,48 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
/* "afl_custom_havoc_mutation", optional */
|
||||
afl->mutator->afl_custom_havoc_mutation =
|
||||
dlsym(dh, "afl_custom_havoc_mutation");
|
||||
if (!afl->mutator->afl_custom_havoc_mutation)
|
||||
if (!afl->mutator->afl_custom_havoc_mutation) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_havoc_mutation' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_havoc_mutation", optional */
|
||||
afl->mutator->afl_custom_havoc_mutation_probability =
|
||||
dlsym(dh, "afl_custom_havoc_mutation_probability");
|
||||
if (!afl->mutator->afl_custom_havoc_mutation_probability)
|
||||
if (!afl->mutator->afl_custom_havoc_mutation_probability) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_queue_get", optional */
|
||||
afl->mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
|
||||
if (!afl->mutator->afl_custom_queue_get)
|
||||
if (!afl->mutator->afl_custom_queue_get) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_queue_get' not found.");
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_queue_new_entry", optional */
|
||||
afl->mutator->afl_custom_queue_new_entry =
|
||||
dlsym(dh, "afl_custom_queue_new_entry");
|
||||
if (!afl->mutator->afl_custom_queue_new_entry)
|
||||
if (!afl->mutator->afl_custom_queue_new_entry) {
|
||||
|
||||
WARNF("Symbol 'afl_custom_queue_new_entry' not found");
|
||||
|
||||
}
|
||||
|
||||
OKF("Custom mutator '%s' installed successfully.", fn);
|
||||
|
||||
/* Initialize the custom mutator */
|
||||
if (afl->mutator->afl_custom_init)
|
||||
if (afl->mutator->afl_custom_init) {
|
||||
|
||||
afl->mutator->data =
|
||||
afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
@ -210,12 +256,19 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max =
|
||||
afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
|
||||
if (unlikely(afl->stage_max) < 0)
|
||||
if (unlikely(afl->stage_max) < 0) {
|
||||
|
||||
FATAL("custom_init_trim error ret: %d", afl->stage_max);
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
|
||||
}
|
||||
|
||||
if (afl->not_on_tty && afl->debug) {
|
||||
|
||||
SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
|
||||
q->len);
|
||||
|
||||
}
|
||||
|
||||
while (afl->stage_cur < afl->stage_max) {
|
||||
|
||||
u8 *retbuf = NULL;
|
||||
@ -227,13 +280,18 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
|
||||
|
||||
if (unlikely(!retbuf))
|
||||
if (unlikely(!retbuf)) {
|
||||
|
||||
FATAL("custom_trim failed (ret %zd)", retlen);
|
||||
else if (unlikely(retlen > orig_len))
|
||||
|
||||
} else if (unlikely(retlen > orig_len)) {
|
||||
|
||||
FATAL(
|
||||
"Trimmed data returned by custom mutator is larger than original "
|
||||
"data");
|
||||
|
||||
}
|
||||
|
||||
write_to_testcase(afl, retbuf, retlen);
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
@ -263,32 +321,45 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
afl->stage_cur =
|
||||
afl->mutator->afl_custom_post_trim(afl->mutator->data, 1);
|
||||
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
if (afl->not_on_tty && afl->debug) {
|
||||
|
||||
SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
|
||||
afl->stage_cur, afl->stage_max, q->len);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Tell the custom mutator that the trimming was unsuccessful */
|
||||
afl->stage_cur =
|
||||
afl->mutator->afl_custom_post_trim(afl->mutator->data, 0);
|
||||
if (unlikely(afl->stage_cur < 0))
|
||||
if (unlikely(afl->stage_cur < 0)) {
|
||||
|
||||
FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
|
||||
}
|
||||
|
||||
if (afl->not_on_tty && afl->debug) {
|
||||
|
||||
SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
|
||||
afl->stage_max);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl);
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
|
||||
|
||||
}
|
||||
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
if (afl->not_on_tty && afl->debug) {
|
||||
|
||||
SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len);
|
||||
|
||||
}
|
||||
|
||||
/* If we have made changes to in_buf, we also need to update the on-disk
|
||||
version of the test case. */
|
||||
|
||||
@ -300,7 +371,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", q->fname);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
|
||||
|
||||
ck_write(fd, in_buf, q->len, q->fname);
|
||||
close(fd);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -111,10 +111,10 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
|
||||
|
||||
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
|
||||
if (!module_name) return NULL;
|
||||
if (!module_name) { return NULL; }
|
||||
|
||||
py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
|
||||
if (!py) PFATAL("Could not allocate memory for python mutator!");
|
||||
if (!py) { PFATAL("Could not allocate memory for python mutator!"); }
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
@ -160,12 +160,12 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
if (py_idx == PY_FUNC_PRE_SAVE) {
|
||||
|
||||
// Implenting the pre_save API is optional for now
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) { PyErr_Print(); }
|
||||
|
||||
} else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
|
||||
|
||||
// Implementing the trim API is optional for now
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) { PyErr_Print(); }
|
||||
py_notrim = 1;
|
||||
|
||||
} else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) &&
|
||||
@ -173,11 +173,11 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
(py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) {
|
||||
|
||||
// Implenting the havoc and queue API is optional for now
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) { PyErr_Print(); }
|
||||
|
||||
} else {
|
||||
|
||||
if (PyErr_Occurred()) PyErr_Print();
|
||||
if (PyErr_Occurred()) { PyErr_Print(); }
|
||||
fprintf(stderr,
|
||||
"Cannot find/call function with index %d in external "
|
||||
"Python module.\n",
|
||||
@ -222,9 +222,12 @@ void finalize_py_module(void *py_mutator) {
|
||||
deinit_py(py_mutator);
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < PY_FUNC_COUNT; ++i)
|
||||
for (i = 0; i < PY_FUNC_COUNT; ++i) {
|
||||
|
||||
Py_XDECREF(py->py_functions[i]);
|
||||
|
||||
}
|
||||
|
||||
Py_DECREF(py->py_module);
|
||||
|
||||
}
|
||||
@ -308,38 +311,67 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
|
||||
|
||||
PyObject **py_functions = py_mutator->py_functions;
|
||||
|
||||
if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = unsupported;
|
||||
if (py_functions[PY_FUNC_INIT]) {
|
||||
|
||||
if (py_functions[PY_FUNC_DEINIT]) afl->mutator->afl_custom_deinit = deinit_py;
|
||||
afl->mutator->afl_custom_init = unsupported;
|
||||
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_DEINIT]) {
|
||||
|
||||
afl->mutator->afl_custom_deinit = deinit_py;
|
||||
|
||||
}
|
||||
|
||||
/* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
|
||||
is quite different from the custom mutator. */
|
||||
afl->mutator->afl_custom_fuzz = fuzz_py;
|
||||
|
||||
if (py_functions[PY_FUNC_PRE_SAVE])
|
||||
if (py_functions[PY_FUNC_PRE_SAVE]) {
|
||||
|
||||
afl->mutator->afl_custom_pre_save = pre_save_py;
|
||||
|
||||
if (py_functions[PY_FUNC_INIT_TRIM])
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_INIT_TRIM]) {
|
||||
|
||||
afl->mutator->afl_custom_init_trim = init_trim_py;
|
||||
|
||||
if (py_functions[PY_FUNC_POST_TRIM])
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_POST_TRIM]) {
|
||||
|
||||
afl->mutator->afl_custom_post_trim = post_trim_py;
|
||||
|
||||
if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py;
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_TRIM]) { afl->mutator->afl_custom_trim = trim_py; }
|
||||
|
||||
if (py_functions[PY_FUNC_HAVOC_MUTATION]) {
|
||||
|
||||
if (py_functions[PY_FUNC_HAVOC_MUTATION])
|
||||
afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
|
||||
|
||||
if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY])
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) {
|
||||
|
||||
afl->mutator->afl_custom_havoc_mutation_probability =
|
||||
havoc_mutation_probability_py;
|
||||
|
||||
if (py_functions[PY_FUNC_QUEUE_GET])
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_QUEUE_GET]) {
|
||||
|
||||
afl->mutator->afl_custom_queue_get = queue_get_py;
|
||||
|
||||
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY])
|
||||
}
|
||||
|
||||
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) {
|
||||
|
||||
afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
|
||||
|
||||
}
|
||||
|
||||
OKF("Python mutator '%s' installed successfully.", module_name);
|
||||
|
||||
/* Initialize the custom mutator */
|
||||
|
@ -38,7 +38,7 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
|
||||
strrchr(q->fname, '/') + 1);
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
close(fd);
|
||||
|
||||
q->passed_det = 1;
|
||||
@ -61,7 +61,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
|
||||
if (symlink(ldest, fn)) {
|
||||
|
||||
s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
close(fd);
|
||||
|
||||
}
|
||||
@ -77,7 +77,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
u8 fn[PATH_MAX];
|
||||
|
||||
if (state == q->fs_redundant) return;
|
||||
if (state == q->fs_redundant) { return; }
|
||||
|
||||
q->fs_redundant = state;
|
||||
|
||||
@ -89,12 +89,12 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
s32 fd;
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
close(fd);
|
||||
|
||||
} else {
|
||||
|
||||
if (unlink(fn)) PFATAL("Unable to remove '%s'", fn);
|
||||
if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); }
|
||||
|
||||
}
|
||||
|
||||
@ -113,17 +113,19 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
q->n_fuzz = 1;
|
||||
q->trace_mini = NULL;
|
||||
|
||||
if (q->depth > afl->max_depth) afl->max_depth = q->depth;
|
||||
if (q->depth > afl->max_depth) { afl->max_depth = q->depth; }
|
||||
|
||||
if (afl->queue_top) {
|
||||
|
||||
afl->queue_top->next = q;
|
||||
afl->queue_top = q;
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
afl->q_prev100 = afl->queue = afl->queue_top = q;
|
||||
|
||||
}
|
||||
|
||||
++afl->queued_paths;
|
||||
++afl->pending_not_fuzzed;
|
||||
|
||||
@ -143,7 +145,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
u8 *fname_orig = NULL;
|
||||
|
||||
/* At the initialization stage, queue_cur is NULL */
|
||||
if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
|
||||
if (afl->queue_cur) { fname_orig = afl->queue_cur->fname; }
|
||||
|
||||
afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
|
||||
fname_orig);
|
||||
@ -188,14 +190,19 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
u64 fuzz_p2 = next_pow2(q->n_fuzz);
|
||||
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE ||
|
||||
unlikely(afl->fixed_seed))
|
||||
unlikely(afl->fixed_seed)) {
|
||||
|
||||
fav_factor = q->len << 2;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
fav_factor = q->exec_us * q->len;
|
||||
|
||||
}
|
||||
|
||||
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
|
||||
winner, and how it compares to us. */
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i)
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
|
||||
if (afl->fsrv.trace_bits[i]) {
|
||||
|
||||
@ -206,29 +213,43 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz);
|
||||
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE ||
|
||||
unlikely(afl->fixed_seed))
|
||||
unlikely(afl->fixed_seed)) {
|
||||
|
||||
top_rated_fav_factor = afl->top_rated[i]->len << 2;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
top_rated_fav_factor =
|
||||
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
|
||||
|
||||
if (fuzz_p2 > top_rated_fuzz_p2)
|
||||
}
|
||||
|
||||
if (fuzz_p2 > top_rated_fuzz_p2) {
|
||||
|
||||
continue;
|
||||
else if (fuzz_p2 == top_rated_fuzz_p2)
|
||||
if (fav_factor > top_rated_fav_factor) continue;
|
||||
|
||||
} else if (fuzz_p2 == top_rated_fuzz_p2) {
|
||||
|
||||
if (fav_factor > top_rated_fav_factor) { continue; }
|
||||
|
||||
}
|
||||
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE ||
|
||||
unlikely(afl->fixed_seed)) {
|
||||
|
||||
if (fav_factor > afl->top_rated[i]->len << 2) continue;
|
||||
if (fav_factor > afl->top_rated[i]->len << 2) { continue; }
|
||||
|
||||
} else {
|
||||
|
||||
if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
|
||||
if (fav_factor >
|
||||
afl->top_rated[i]->exec_us * afl->top_rated[i]->len) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Looks like we're going to win. Decrease ref count for the
|
||||
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
|
||||
|
||||
@ -249,7 +270,6 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
if (!q->trace_mini) {
|
||||
|
||||
u32 len = (afl->fsrv.map_size >> 3);
|
||||
if (len == 0) len = 1;
|
||||
q->trace_mini = ck_alloc(len);
|
||||
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
|
||||
|
||||
@ -259,6 +279,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* The second part of the mechanism discussed above is a routine that
|
||||
@ -272,11 +294,9 @@ void cull_queue(afl_state_t *afl) {
|
||||
struct queue_entry *q;
|
||||
u32 len = (afl->fsrv.map_size >> 3);
|
||||
u32 i;
|
||||
u8 temp_v[MAP_SIZE >> 3];
|
||||
u8 * temp_v = afl->map_tmp_buf;
|
||||
|
||||
if (len == 0) len = 1;
|
||||
|
||||
if (afl->dumb_mode || !afl->score_changed) return;
|
||||
if (afl->dumb_mode || !afl->score_changed) { return; }
|
||||
|
||||
afl->score_changed = 0;
|
||||
|
||||
@ -297,25 +317,38 @@ void cull_queue(afl_state_t *afl) {
|
||||
/* Let's see if anything in the bitmap isn't captured in temp_v.
|
||||
If yes, and if it has a afl->top_rated[] contender, let's use it. */
|
||||
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i)
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
|
||||
if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) {
|
||||
|
||||
u32 j = len;
|
||||
|
||||
/* Remove all bits belonging to the current entry from temp_v. */
|
||||
|
||||
while (j--)
|
||||
if (afl->top_rated[i]->trace_mini[j])
|
||||
while (j--) {
|
||||
|
||||
if (afl->top_rated[i]->trace_mini[j]) {
|
||||
|
||||
temp_v[j] &= ~afl->top_rated[i]->trace_mini[j];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
afl->top_rated[i]->favored = 1;
|
||||
++afl->queued_favored;
|
||||
|
||||
if (afl->top_rated[i]->fuzz_level == 0 || !afl->top_rated[i]->was_fuzzed)
|
||||
if (afl->top_rated[i]->fuzz_level == 0 ||
|
||||
!afl->top_rated[i]->was_fuzzed) {
|
||||
|
||||
++afl->pending_favored;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
q = afl->queue;
|
||||
|
||||
while (q) {
|
||||
@ -350,39 +383,67 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
if (afl->schedule != MMOPT && afl->schedule != RARE &&
|
||||
likely(!afl->fixed_seed)) {
|
||||
|
||||
if (q->exec_us * 0.1 > avg_exec_us)
|
||||
if (q->exec_us * 0.1 > avg_exec_us) {
|
||||
|
||||
perf_score = 10;
|
||||
else if (q->exec_us * 0.25 > avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 0.25 > avg_exec_us) {
|
||||
|
||||
perf_score = 25;
|
||||
else if (q->exec_us * 0.5 > avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 0.5 > avg_exec_us) {
|
||||
|
||||
perf_score = 50;
|
||||
else if (q->exec_us * 0.75 > avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 0.75 > avg_exec_us) {
|
||||
|
||||
perf_score = 75;
|
||||
else if (q->exec_us * 4 < avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 4 < avg_exec_us) {
|
||||
|
||||
perf_score = 300;
|
||||
else if (q->exec_us * 3 < avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 3 < avg_exec_us) {
|
||||
|
||||
perf_score = 200;
|
||||
else if (q->exec_us * 2 < avg_exec_us)
|
||||
|
||||
} else if (q->exec_us * 2 < avg_exec_us) {
|
||||
|
||||
perf_score = 150;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Adjust score based on bitmap size. The working theory is that better
|
||||
coverage translates to better targets. Multiplier from 0.25x to 3x. */
|
||||
|
||||
if (q->bitmap_size * 0.3 > avg_bitmap_size)
|
||||
if (q->bitmap_size * 0.3 > avg_bitmap_size) {
|
||||
|
||||
perf_score *= 3;
|
||||
else if (q->bitmap_size * 0.5 > avg_bitmap_size)
|
||||
|
||||
} else if (q->bitmap_size * 0.5 > avg_bitmap_size) {
|
||||
|
||||
perf_score *= 2;
|
||||
else if (q->bitmap_size * 0.75 > avg_bitmap_size)
|
||||
|
||||
} else if (q->bitmap_size * 0.75 > avg_bitmap_size) {
|
||||
|
||||
perf_score *= 1.5;
|
||||
else if (q->bitmap_size * 3 < avg_bitmap_size)
|
||||
|
||||
} else if (q->bitmap_size * 3 < avg_bitmap_size) {
|
||||
|
||||
perf_score *= 0.25;
|
||||
else if (q->bitmap_size * 2 < avg_bitmap_size)
|
||||
|
||||
} else if (q->bitmap_size * 2 < avg_bitmap_size) {
|
||||
|
||||
perf_score *= 0.5;
|
||||
else if (q->bitmap_size * 1.5 < avg_bitmap_size)
|
||||
|
||||
} else if (q->bitmap_size * 1.5 < avg_bitmap_size) {
|
||||
|
||||
perf_score *= 0.75;
|
||||
|
||||
}
|
||||
|
||||
/* Adjust score based on handicap. Handicap is proportional to how late
|
||||
in the game we learned about this path. Latecomers are allowed to run
|
||||
for a bit longer until they catch up with the rest. */
|
||||
@ -405,11 +466,19 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
switch (q->depth) {
|
||||
|
||||
case 0 ... 3: break;
|
||||
case 4 ... 7: perf_score *= 2; break;
|
||||
case 8 ... 13: perf_score *= 3; break;
|
||||
case 14 ... 25: perf_score *= 4; break;
|
||||
default: perf_score *= 5;
|
||||
case 0 ... 3:
|
||||
break;
|
||||
case 4 ... 7:
|
||||
perf_score *= 2;
|
||||
break;
|
||||
case 8 ... 13:
|
||||
perf_score *= 3;
|
||||
break;
|
||||
case 14 ... 25:
|
||||
perf_score *= 4;
|
||||
break;
|
||||
default:
|
||||
perf_score *= 5;
|
||||
|
||||
}
|
||||
|
||||
@ -421,9 +490,12 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
switch (afl->schedule) {
|
||||
|
||||
case EXPLORE: break;
|
||||
case EXPLORE:
|
||||
break;
|
||||
|
||||
case EXPLOIT: factor = MAX_FACTOR; break;
|
||||
case EXPLOIT:
|
||||
factor = MAX_FACTOR;
|
||||
break;
|
||||
|
||||
case COE:
|
||||
fuzz_total = 0;
|
||||
@ -438,16 +510,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(!n_paths)) FATAL("Queue state corrupt");
|
||||
if (unlikely(!n_paths)) { FATAL("Queue state corrupt"); }
|
||||
|
||||
fuzz_mu = fuzz_total / n_paths;
|
||||
if (fuzz <= fuzz_mu) {
|
||||
|
||||
if (q->fuzz_level < 16)
|
||||
if (q->fuzz_level < 16) {
|
||||
|
||||
factor = ((u32)(1 << q->fuzz_level));
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
factor = MAX_FACTOR;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
factor = 0;
|
||||
@ -457,13 +534,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
break;
|
||||
|
||||
case FAST:
|
||||
if (q->fuzz_level < 16)
|
||||
if (q->fuzz_level < 16) {
|
||||
|
||||
factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz));
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break;
|
||||
case LIN:
|
||||
factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz);
|
||||
break;
|
||||
|
||||
case QUAD:
|
||||
factor = q->fuzz_level * q->fuzz_level / (fuzz == 0 ? 1 : fuzz);
|
||||
@ -480,7 +565,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
(afl->max_depth - q->depth)) / 5));
|
||||
*/
|
||||
// put focus on the last 5 entries
|
||||
if (afl->max_depth - q->depth < 5) perf_score *= 2;
|
||||
if (afl->max_depth - q->depth < 5) { perf_score *= 2; }
|
||||
|
||||
break;
|
||||
|
||||
@ -496,26 +581,35 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
break;
|
||||
|
||||
default: PFATAL("Unknown Power Schedule");
|
||||
default:
|
||||
PFATAL("Unknown Power Schedule");
|
||||
|
||||
}
|
||||
|
||||
if (factor > MAX_FACTOR) factor = MAX_FACTOR;
|
||||
if (factor > MAX_FACTOR) { factor = MAX_FACTOR; }
|
||||
|
||||
perf_score *= factor / POWER_BETA;
|
||||
|
||||
// MOpt mode
|
||||
if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3)
|
||||
if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3) {
|
||||
|
||||
perf_score *= 2;
|
||||
else if (perf_score < 1)
|
||||
|
||||
} else if (perf_score < 1) {
|
||||
|
||||
// Add a lower bound to AFLFast's energy assignment strategies
|
||||
perf_score = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Make sure that we don't go over limit. */
|
||||
|
||||
if (perf_score > afl->havoc_max_mult * 100)
|
||||
if (perf_score > afl->havoc_max_mult * 100) {
|
||||
|
||||
perf_score = afl->havoc_max_mult * 100;
|
||||
|
||||
}
|
||||
|
||||
return perf_score;
|
||||
|
||||
}
|
||||
|
@ -73,20 +73,25 @@ static struct range *pop_biggest_range(struct range **ranges) {
|
||||
|
||||
if (rmax) {
|
||||
|
||||
if (prev_rmax)
|
||||
if (prev_rmax) {
|
||||
|
||||
prev_rmax->next = rmax->next;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
*ranges = rmax->next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rmax;
|
||||
|
||||
}
|
||||
|
||||
static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) {
|
||||
|
||||
if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1;
|
||||
if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
|
||||
|
||||
*cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
return 0;
|
||||
@ -96,9 +101,12 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) {
|
||||
static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) {
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < len; ++i)
|
||||
for (i = 0; i < len; ++i) {
|
||||
|
||||
buf[i] = rand_below(afl, 256);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
@ -131,9 +139,12 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
|
||||
u32 cksum;
|
||||
u64 start_us = get_cur_time_us();
|
||||
if (unlikely(get_exec_checksum(afl, buf, len, &cksum)))
|
||||
if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) {
|
||||
|
||||
goto checksum_fail;
|
||||
|
||||
}
|
||||
|
||||
u64 stop_us = get_cur_time_us();
|
||||
|
||||
/* Discard if the mutations change the paths or if it is too decremental
|
||||
@ -159,7 +170,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->stage_cur < afl->stage_max) afl->queue_cur->fully_colorized = 1;
|
||||
if (afl->stage_cur < afl->stage_max) { afl->queue_cur->fully_colorized = 1; }
|
||||
|
||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt;
|
||||
@ -175,6 +186,9 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
|
||||
}
|
||||
|
||||
ck_free(rng);
|
||||
rng = NULL;
|
||||
|
||||
// save the input with the high entropy
|
||||
|
||||
if (needs_write) {
|
||||
@ -192,7 +206,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", afl->queue_cur->fname);
|
||||
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
|
||||
@ -204,7 +218,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
|
||||
return 0;
|
||||
|
||||
checksum_fail:
|
||||
if (rng) ck_free(rng);
|
||||
if (rng) { ck_free(rng); }
|
||||
ck_free(backup);
|
||||
|
||||
while (ranges) {
|
||||
@ -230,15 +244,20 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
|
||||
|
||||
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1;
|
||||
if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
|
||||
|
||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
if (unlikely(new_hit_cnt != orig_hit_cnt))
|
||||
if (unlikely(new_hit_cnt != orig_hit_cnt)) {
|
||||
|
||||
*status = 1;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
*status = 2;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -265,66 +284,84 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
||||
if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) {
|
||||
|
||||
*buf_64 = repl;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) return 1;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||
*buf_64 = pattern;
|
||||
|
||||
}
|
||||
|
||||
// reverse encoding
|
||||
if (do_reverse)
|
||||
if (do_reverse) {
|
||||
|
||||
if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
|
||||
SWAP64(o_pattern), idx, orig_buf, buf,
|
||||
len, 0, status)))
|
||||
len, 0, status))) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (SHAPE_BYTES(h->shape) == 4 || *status == 2) {
|
||||
|
||||
if (its_len >= 4 && *buf_32 == (u32)pattern &&
|
||||
*o_buf_32 == (u32)o_pattern) {
|
||||
|
||||
*buf_32 = (u32)repl;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) return 1;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||
*buf_32 = pattern;
|
||||
|
||||
}
|
||||
|
||||
// reverse encoding
|
||||
if (do_reverse)
|
||||
if (do_reverse) {
|
||||
|
||||
if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
|
||||
SWAP32(o_pattern), idx, orig_buf, buf,
|
||||
len, 0, status)))
|
||||
len, 0, status))) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (SHAPE_BYTES(h->shape) == 2 || *status == 2) {
|
||||
|
||||
if (its_len >= 2 && *buf_16 == (u16)pattern &&
|
||||
*o_buf_16 == (u16)o_pattern) {
|
||||
|
||||
*buf_16 = (u16)repl;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) return 1;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||
*buf_16 = (u16)pattern;
|
||||
|
||||
}
|
||||
|
||||
// reverse encoding
|
||||
if (do_reverse)
|
||||
if (do_reverse) {
|
||||
|
||||
if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
|
||||
SWAP16(o_pattern), idx, orig_buf, buf,
|
||||
len, 0, status)))
|
||||
len, 0, status))) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (SHAPE_BYTES(h->shape) == 1 || *status == 2) {
|
||||
|
||||
if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) {
|
||||
|
||||
*buf_8 = (u8)repl;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) return 1;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||
*buf_8 = (u8)pattern;
|
||||
|
||||
}
|
||||
@ -343,14 +380,21 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
|
||||
u8 cons_ff = 0, cons_0 = 0;
|
||||
for (k = 0; k < shape; ++k) {
|
||||
|
||||
if (b[k] == 0)
|
||||
if (b[k] == 0) {
|
||||
|
||||
++cons_0;
|
||||
else if (b[k] == 0xff)
|
||||
|
||||
} else if (b[k] == 0xff) {
|
||||
|
||||
++cons_0;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
cons_0 = cons_ff = 0;
|
||||
|
||||
if (cons_0 > 1 || cons_ff > 1) return;
|
||||
}
|
||||
|
||||
if (cons_0 > 1 || cons_ff > 1) { return; }
|
||||
|
||||
}
|
||||
|
||||
@ -359,7 +403,8 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
|
||||
u64 rev;
|
||||
switch (shape) {
|
||||
|
||||
case 1: break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
rev = SWAP16((u16)v);
|
||||
maybe_add_auto((u8 *)afl, (u8 *)&rev, shape);
|
||||
@ -383,7 +428,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
u32 i, j, idx;
|
||||
|
||||
u32 loggeds = h->hits;
|
||||
if (h->hits > CMP_MAP_H) loggeds = CMP_MAP_H;
|
||||
if (h->hits > CMP_MAP_H) { loggeds = CMP_MAP_H; }
|
||||
|
||||
u8 status = 0;
|
||||
// opt not in the paper
|
||||
@ -410,12 +455,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
} else {
|
||||
|
||||
if (s_v0 != o->v0) s_v0_fixed = 0;
|
||||
if (s_v1 != o->v1) s_v1_fixed = 0;
|
||||
if (s_v0 + 1 != o->v0) s_v0_inc = 0;
|
||||
if (s_v1 + 1 != o->v1) s_v1_inc = 0;
|
||||
if (s_v0 - 1 != o->v0) s_v0_dec = 0;
|
||||
if (s_v1 - 1 != o->v1) s_v1_dec = 0;
|
||||
if (s_v0 != o->v0) { s_v0_fixed = 0; }
|
||||
if (s_v1 != o->v1) { s_v1_fixed = 0; }
|
||||
if (s_v0 + 1 != o->v0) { s_v0_inc = 0; }
|
||||
if (s_v1 + 1 != o->v1) { s_v1_inc = 0; }
|
||||
if (s_v0 - 1 != o->v0) { s_v0_dec = 0; }
|
||||
if (s_v1 - 1 != o->v1) { s_v1_dec = 0; }
|
||||
s_v0 = o->v0;
|
||||
s_v1 = o->v1;
|
||||
|
||||
@ -424,32 +469,56 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i];
|
||||
|
||||
// opt not in the paper
|
||||
for (j = 0; j < i; ++j)
|
||||
for (j = 0; j < i; ++j) {
|
||||
|
||||
if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
|
||||
afl->shm.cmp_map->log[key][i].v1 == o->v1)
|
||||
afl->shm.cmp_map->log[key][i].v1 == o->v1) {
|
||||
|
||||
goto cmp_fuzz_next_iter;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (idx = 0; idx < len && fails < 8; ++idx) {
|
||||
|
||||
if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
|
||||
orig_buf, buf, len, 1, &status)))
|
||||
return 1;
|
||||
if (status == 2)
|
||||
++fails;
|
||||
else if (status == 1)
|
||||
break;
|
||||
orig_buf, buf, len, 1, &status))) {
|
||||
|
||||
if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
|
||||
orig_buf, buf, len, 1, &status)))
|
||||
return 1;
|
||||
if (status == 2)
|
||||
|
||||
}
|
||||
|
||||
if (status == 2) {
|
||||
|
||||
++fails;
|
||||
else if (status == 1)
|
||||
|
||||
} else if (status == 1) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (status == 1) found_one = 1;
|
||||
if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
|
||||
orig_buf, buf, len, 1, &status))) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (status == 2) {
|
||||
|
||||
++fails;
|
||||
|
||||
} else if (status == 1) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (status == 1) { found_one = 1; }
|
||||
|
||||
// If failed, add to dictionary
|
||||
if (fails == 8) {
|
||||
@ -481,7 +550,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++;
|
||||
if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
|
||||
|
||||
return 0;
|
||||
|
||||
@ -502,11 +571,14 @@ static u8 rtn_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
||||
for (i = 0; i < its_len; ++i) {
|
||||
|
||||
if (pattern[idx + i] != buf[idx + i] ||
|
||||
o_pattern[idx + i] != orig_buf[idx + i] || *status == 1)
|
||||
o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
buf[idx + i] = repl[idx + i];
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) return 1;
|
||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||
|
||||
}
|
||||
|
||||
@ -521,7 +593,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
u32 i, j, idx;
|
||||
|
||||
u32 loggeds = h->hits;
|
||||
if (h->hits > CMP_MAP_RTN_H) loggeds = CMP_MAP_RTN_H;
|
||||
if (h->hits > CMP_MAP_RTN_H) { loggeds = CMP_MAP_RTN_H; }
|
||||
|
||||
u8 status = 0;
|
||||
// opt not in the paper
|
||||
@ -539,32 +611,56 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
&((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i];
|
||||
|
||||
// opt not in the paper
|
||||
for (j = 0; j < i; ++j)
|
||||
for (j = 0; j < i; ++j) {
|
||||
|
||||
if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o,
|
||||
sizeof(struct cmpfn_operands)))
|
||||
sizeof(struct cmpfn_operands))) {
|
||||
|
||||
goto rtn_fuzz_next_iter;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (idx = 0; idx < len && fails < 8; ++idx) {
|
||||
|
||||
if (unlikely(rtn_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
|
||||
orig_buf, buf, len, &status)))
|
||||
return 1;
|
||||
if (status == 2)
|
||||
++fails;
|
||||
else if (status == 1)
|
||||
break;
|
||||
orig_buf, buf, len, &status))) {
|
||||
|
||||
if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
|
||||
orig_buf, buf, len, &status)))
|
||||
return 1;
|
||||
if (status == 2)
|
||||
|
||||
}
|
||||
|
||||
if (status == 2) {
|
||||
|
||||
++fails;
|
||||
else if (status == 1)
|
||||
|
||||
} else if (status == 1) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (status == 1) found_one = 1;
|
||||
if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
|
||||
orig_buf, buf, len, &status))) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if (status == 2) {
|
||||
|
||||
++fails;
|
||||
|
||||
} else if (status == 1) {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (status == 1) { found_one = 1; }
|
||||
|
||||
// If failed, add to dictionary
|
||||
if (fails == 8) {
|
||||
@ -589,7 +685,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++;
|
||||
if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
|
||||
|
||||
return 0;
|
||||
|
||||
@ -602,25 +698,31 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
|
||||
u32 exec_cksum) {
|
||||
|
||||
u8 r = 1;
|
||||
if (afl->orig_cmp_map == NULL)
|
||||
if (afl->orig_cmp_map == NULL) {
|
||||
|
||||
afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
|
||||
|
||||
if (afl->pass_stats == NULL)
|
||||
}
|
||||
|
||||
if (afl->pass_stats == NULL) {
|
||||
|
||||
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
|
||||
|
||||
}
|
||||
|
||||
// do it manually, forkserver clear only afl->fsrv.trace_bits
|
||||
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers));
|
||||
|
||||
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1;
|
||||
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
|
||||
|
||||
memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
|
||||
|
||||
if (unlikely(colorization(afl, buf, len, exec_cksum))) return 1;
|
||||
if (unlikely(colorization(afl, buf, len, exec_cksum))) { return 1; }
|
||||
|
||||
// do it manually, forkserver clear only afl->fsrv.trace_bits
|
||||
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers));
|
||||
|
||||
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1;
|
||||
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
|
||||
|
||||
u64 orig_hit_cnt, new_hit_cnt;
|
||||
u64 orig_execs = afl->fsrv.total_execs;
|
||||
@ -634,33 +736,41 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
|
||||
u32 k;
|
||||
for (k = 0; k < CMP_MAP_W; ++k) {
|
||||
|
||||
if (!afl->shm.cmp_map->headers[k].hits) continue;
|
||||
if (!afl->shm.cmp_map->headers[k].hits) { continue; }
|
||||
|
||||
if (afl->pass_stats[k].total &&
|
||||
(rand_below(afl, afl->pass_stats[k].total) >=
|
||||
afl->pass_stats[k].faileds ||
|
||||
afl->pass_stats[k].total == 0xff))
|
||||
afl->pass_stats[k].total == 0xff)) {
|
||||
|
||||
afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp
|
||||
|
||||
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS)
|
||||
}
|
||||
|
||||
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
|
||||
|
||||
afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
afl->stage_max +=
|
||||
MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (k = 0; k < CMP_MAP_W; ++k) {
|
||||
|
||||
if (!afl->shm.cmp_map->headers[k].hits) continue;
|
||||
if (!afl->shm.cmp_map->headers[k].hits) { continue; }
|
||||
|
||||
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
|
||||
|
||||
if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) goto exit_its;
|
||||
if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; }
|
||||
|
||||
} else {
|
||||
|
||||
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) goto exit_its;
|
||||
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; }
|
||||
|
||||
}
|
||||
|
||||
|
@ -72,9 +72,12 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
|
||||
size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
|
||||
len, &new_buf);
|
||||
|
||||
if (unlikely(!new_buf))
|
||||
if (unlikely(!new_buf)) {
|
||||
|
||||
FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
|
||||
|
||||
}
|
||||
|
||||
/* everything as planned. use the new data. */
|
||||
afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size);
|
||||
|
||||
@ -108,27 +111,34 @@ static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", afl->fsrv.out_file);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); }
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
if (skip_at) ck_write(fd, mem, skip_at, afl->fsrv.out_file);
|
||||
}
|
||||
|
||||
if (skip_at) { ck_write(fd, mem, skip_at, afl->fsrv.out_file); }
|
||||
|
||||
u8 *memu8 = mem;
|
||||
if (tail_len)
|
||||
if (tail_len) {
|
||||
|
||||
ck_write(fd, memu8 + skip_at + skip_len, tail_len, afl->fsrv.out_file);
|
||||
|
||||
}
|
||||
|
||||
if (!afl->fsrv.out_file) {
|
||||
|
||||
if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed");
|
||||
if (ftruncate(fd, len - skip_len)) { PFATAL("ftruncate() failed"); }
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Calibrate a new test case. This is done when processing the input directory
|
||||
@ -151,10 +161,13 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
trying to calibrate already-added finds. This helps avoid trouble due
|
||||
to intermittent latency. */
|
||||
|
||||
if (!from_queue || afl->resuming_fuzz)
|
||||
if (!from_queue || afl->resuming_fuzz) {
|
||||
|
||||
use_tmout = MAX(afl->fsrv.exec_tmout + CAL_TMOUT_ADD,
|
||||
afl->fsrv.exec_tmout * CAL_TMOUT_PERC / 100);
|
||||
|
||||
}
|
||||
|
||||
++q->cal_failed;
|
||||
|
||||
afl->stage_name = "calibration";
|
||||
@ -177,18 +190,24 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
|
||||
}
|
||||
|
||||
if (q->exec_cksum)
|
||||
if (q->exec_cksum) {
|
||||
|
||||
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
|
||||
|
||||
}
|
||||
|
||||
start_us = get_cur_time_us();
|
||||
|
||||
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
|
||||
|
||||
u32 cksum;
|
||||
|
||||
if (!first_run && !(afl->stage_cur % afl->stats_update_freq))
|
||||
if (!first_run && !(afl->stage_cur % afl->stats_update_freq)) {
|
||||
|
||||
show_stats(afl);
|
||||
|
||||
}
|
||||
|
||||
write_to_testcase(afl, use_mem, q->len);
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
||||
@ -196,7 +215,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
||||
we want to bail out quickly. */
|
||||
|
||||
if (afl->stop_soon || fault != afl->crash_mode) goto abort_calibration;
|
||||
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
|
||||
|
||||
if (!afl->dumb_mode && !afl->stage_cur &&
|
||||
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
||||
@ -211,7 +230,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
if (q->exec_cksum != cksum) {
|
||||
|
||||
u8 hnb = has_new_bits(afl, afl->virgin_bits);
|
||||
if (hnb > new_bits) new_bits = hnb;
|
||||
if (hnb > new_bits) { new_bits = hnb; }
|
||||
|
||||
if (q->exec_cksum) {
|
||||
|
||||
@ -220,11 +239,14 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
|
||||
if (unlikely(!afl->var_bytes[i]) &&
|
||||
unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i]))
|
||||
unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) {
|
||||
|
||||
afl->var_bytes[i] = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var_detected = 1;
|
||||
afl->stage_max = CAL_CYCLES_LONG;
|
||||
|
||||
@ -261,9 +283,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
parent. This is a non-critical problem, but something to warn the user
|
||||
about. */
|
||||
|
||||
if (!afl->dumb_mode && first_run && !fault && !new_bits)
|
||||
if (!afl->dumb_mode && first_run && !fault && !new_bits) {
|
||||
|
||||
fault = FSRV_RUN_NOBITS;
|
||||
|
||||
}
|
||||
|
||||
abort_calibration:
|
||||
|
||||
if (new_bits == 2 && !q->has_new_cov) {
|
||||
@ -292,7 +317,7 @@ abort_calibration:
|
||||
afl->stage_cur = old_sc;
|
||||
afl->stage_max = old_sm;
|
||||
|
||||
if (!first_run) show_stats(afl);
|
||||
if (!first_run) { show_stats(afl); }
|
||||
|
||||
return fault;
|
||||
|
||||
@ -307,7 +332,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
u32 sync_cnt = 0;
|
||||
|
||||
sd = opendir(afl->sync_dir);
|
||||
if (!sd) PFATAL("Unable to open '%s'", afl->sync_dir);
|
||||
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
|
||||
|
||||
afl->stage_max = afl->stage_cur = 0;
|
||||
afl->cur_depth = 0;
|
||||
@ -326,9 +351,12 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
/* Skip dot files and our own output directory. */
|
||||
|
||||
if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name))
|
||||
if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Skip anything that doesn't have a queue/ subdirectory. */
|
||||
|
||||
qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name);
|
||||
@ -347,9 +375,13 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600);
|
||||
|
||||
if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path);
|
||||
if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); }
|
||||
|
||||
if (read(id_fd, &min_accept, sizeof(u32)) > 0) lseek(id_fd, 0, SEEK_SET);
|
||||
if (read(id_fd, &min_accept, sizeof(u32)) > 0) {
|
||||
|
||||
lseek(id_fd, 0, SEEK_SET);
|
||||
|
||||
}
|
||||
|
||||
next_min_accept = min_accept;
|
||||
|
||||
@ -372,14 +404,20 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
if (qd_ent->d_name[0] == '.' ||
|
||||
sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 ||
|
||||
afl->syncing_case < min_accept)
|
||||
afl->syncing_case < min_accept) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* OK, sounds like a new one. Let's give it a try. */
|
||||
|
||||
if (afl->syncing_case >= next_min_accept)
|
||||
if (afl->syncing_case >= next_min_accept) {
|
||||
|
||||
next_min_accept = afl->syncing_case + 1;
|
||||
|
||||
}
|
||||
|
||||
path = alloc_printf("%s/%s", qd_path, qd_ent->d_name);
|
||||
|
||||
/* Allow this to fail in case the other fuzzer is resuming or so... */
|
||||
@ -393,7 +431,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) PFATAL("fstat() failed");
|
||||
if (fstat(fd, &st)) { PFATAL("fstat() failed"); }
|
||||
|
||||
/* Ignore zero-sized or oversized files. */
|
||||
|
||||
@ -402,7 +440,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
u8 fault;
|
||||
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path);
|
||||
if (mem == MAP_FAILED) { PFATAL("Unable to mmap '%s'", path); }
|
||||
|
||||
/* See what happens. We rely on save_if_interesting() to catch major
|
||||
errors and save the test case. */
|
||||
@ -411,7 +449,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) goto close_sync;
|
||||
if (afl->stop_soon) { goto close_sync; }
|
||||
|
||||
afl->syncing_party = sd_ent->d_name;
|
||||
afl->queued_imported +=
|
||||
@ -420,7 +458,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
munmap(mem, st.st_size);
|
||||
|
||||
if (!(afl->stage_cur++ % afl->stats_update_freq)) show_stats(afl);
|
||||
if (!(afl->stage_cur++ % afl->stats_update_freq)) { show_stats(afl); }
|
||||
|
||||
}
|
||||
|
||||
@ -450,9 +488,12 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
/* Custom mutator trimmer */
|
||||
if (afl->mutator && afl->mutator->afl_custom_trim)
|
||||
if (afl->mutator && afl->mutator->afl_custom_trim) {
|
||||
|
||||
return trim_case_custom(afl, q, in_buf);
|
||||
|
||||
}
|
||||
|
||||
u8 needs_write = 0, fault = 0;
|
||||
u32 trim_exec = 0;
|
||||
u32 remove_len;
|
||||
@ -464,7 +505,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
detected, it will still work to some extent, so we don't check for
|
||||
this. */
|
||||
|
||||
if (q->len < 5) return 0;
|
||||
if (q->len < 5) { return 0; }
|
||||
|
||||
afl->stage_name = afl->stage_name_buf;
|
||||
afl->bytes_trim_in += q->len;
|
||||
@ -499,7 +540,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
++afl->trim_execs;
|
||||
|
||||
if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming;
|
||||
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
|
||||
|
||||
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
|
||||
*/
|
||||
@ -531,13 +572,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
remove_pos += remove_len;
|
||||
|
||||
}
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl);
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
|
||||
++afl->stage_cur;
|
||||
|
||||
}
|
||||
@ -564,7 +607,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", q->fname);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
|
||||
|
||||
ck_write(fd, in_buf, q->len, q->fname);
|
||||
close(fd);
|
||||
@ -595,7 +638,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
size_t post_len =
|
||||
afl->post_handler(afl->post_data, out_buf, len, &post_buf);
|
||||
if (!post_buf || !post_len) return 0;
|
||||
if (!post_buf || !post_len) { return 0; }
|
||||
out_buf = post_buf;
|
||||
len = post_len;
|
||||
|
||||
@ -605,7 +648,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) return 1;
|
||||
if (afl->stop_soon) { return 1; }
|
||||
|
||||
if (fault == FSRV_RUN_TMOUT) {
|
||||
|
||||
@ -616,10 +659,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
afl->subseq_tmouts = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Users can hit us with SIGUSR1 to request the current input
|
||||
to be abandoned. */
|
||||
|
||||
@ -636,9 +681,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
afl->queued_discovered += save_if_interesting(afl, out_buf, len, fault);
|
||||
|
||||
if (!(afl->stage_cur % afl->stats_update_freq) ||
|
||||
afl->stage_cur + 1 == afl->stage_max)
|
||||
afl->stage_cur + 1 == afl->stage_max) {
|
||||
|
||||
show_stats(afl);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -75,12 +75,14 @@ list_t afl_states = {.element_prealloc_count = 0};
|
||||
|
||||
/* Initializes an afl_state_t. */
|
||||
|
||||
void afl_state_init(afl_state_t *afl) {
|
||||
void afl_state_init(afl_state_t *afl, uint32_t map_size) {
|
||||
|
||||
/* thanks to this memset, growing vars like out_buf
|
||||
and out_size are NULL/0 by default. */
|
||||
memset(afl, 0, sizeof(afl_state_t));
|
||||
|
||||
if (!map_size) { afl->shm.map_size = MAP_SIZE; }
|
||||
|
||||
afl->w_init = 0.9;
|
||||
afl->w_end = 0.3;
|
||||
afl->g_max = 5000;
|
||||
@ -97,9 +99,18 @@ void afl_state_init(afl_state_t *afl) {
|
||||
afl->cpu_aff = -1; /* Selected CPU core */
|
||||
#endif /* HAVE_AFFINITY */
|
||||
|
||||
afl->fsrv.use_stdin = 1;
|
||||
afl->virgin_bits = ck_alloc(map_size);
|
||||
afl->virgin_tmout = ck_alloc(map_size);
|
||||
afl->virgin_crash = ck_alloc(map_size);
|
||||
afl->var_bytes = ck_alloc(map_size);
|
||||
afl->top_rated = ck_alloc(map_size * sizeof(void *));
|
||||
afl->clean_trace = ck_alloc(map_size);
|
||||
afl->clean_trace_custom = ck_alloc(map_size);
|
||||
afl->first_trace = ck_alloc(map_size);
|
||||
afl->map_tmp_buf = ck_alloc(map_size);
|
||||
|
||||
afl->fsrv.map_size = MAP_SIZE;
|
||||
afl->fsrv.use_stdin = 1;
|
||||
afl->fsrv.map_size = map_size;
|
||||
afl->fsrv.function_opt = (u8 *)afl;
|
||||
afl->fsrv.function_ptr = &maybe_add_auto;
|
||||
|
||||
@ -333,12 +344,14 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (match == 0) {
|
||||
|
||||
WARNF("Mistyped AFL environment variable: %s", env);
|
||||
@ -350,7 +363,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (found) sleep(2);
|
||||
if (found) { sleep(2); }
|
||||
|
||||
}
|
||||
|
||||
@ -358,18 +371,28 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
|
||||
void afl_state_deinit(afl_state_t *afl) {
|
||||
|
||||
if (afl->post_deinit) afl->post_deinit(afl->post_data);
|
||||
if (afl->in_place_resume) ck_free(afl->in_dir);
|
||||
if (afl->sync_id) ck_free(afl->out_dir);
|
||||
if (afl->pass_stats) ck_free(afl->pass_stats);
|
||||
if (afl->orig_cmp_map) ck_free(afl->orig_cmp_map);
|
||||
if (afl->post_deinit) { afl->post_deinit(afl->post_data); }
|
||||
if (afl->in_place_resume) { ck_free(afl->in_dir); }
|
||||
if (afl->sync_id) { ck_free(afl->out_dir); }
|
||||
if (afl->pass_stats) { ck_free(afl->pass_stats); }
|
||||
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
|
||||
|
||||
free(afl->out_buf);
|
||||
free(afl->out_scratch_buf);
|
||||
free(afl->eff_buf);
|
||||
free(afl->in_buf);
|
||||
free(afl->in_scratch_buf);
|
||||
free(afl->ex_buf);
|
||||
if (afl->out_buf) { free(afl->out_buf); }
|
||||
if (afl->out_scratch_buf) { free(afl->out_scratch_buf); }
|
||||
if (afl->eff_buf) { free(afl->eff_buf); }
|
||||
if (afl->in_buf) { free(afl->in_buf); }
|
||||
if (afl->in_scratch_buf) { free(afl->in_scratch_buf); }
|
||||
if (afl->ex_buf) { free(afl->ex_buf); }
|
||||
|
||||
ck_free(afl->virgin_bits);
|
||||
ck_free(afl->virgin_tmout);
|
||||
ck_free(afl->virgin_crash);
|
||||
ck_free(afl->var_bytes);
|
||||
ck_free(afl->top_rated);
|
||||
ck_free(afl->clean_trace);
|
||||
ck_free(afl->clean_trace_custom);
|
||||
ck_free(afl->first_trace);
|
||||
ck_free(afl->map_tmp_buf);
|
||||
|
||||
list_remove(&afl_states, afl);
|
||||
|
||||
|
@ -43,11 +43,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
|
||||
f = fdopen(fd, "w");
|
||||
|
||||
if (!f) PFATAL("fdopen() failed");
|
||||
if (!f) { PFATAL("fdopen() failed"); }
|
||||
|
||||
/* Keep last values in case we're called from another context
|
||||
where exec/sec stats and such are not readily available. */
|
||||
@ -65,7 +65,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
|
||||
}
|
||||
|
||||
if (getrusage(RUSAGE_CHILDREN, &rus)) rus.ru_maxrss = 0;
|
||||
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
|
||||
|
||||
fprintf(
|
||||
f,
|
||||
@ -145,16 +145,20 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
|
||||
void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
|
||||
|
||||
if (afl->plot_prev_qp == afl->queued_paths &&
|
||||
if (unlikely(afl->plot_prev_qp == afl->queued_paths &&
|
||||
afl->plot_prev_pf == afl->pending_favored &&
|
||||
afl->plot_prev_pnf == afl->pending_not_fuzzed &&
|
||||
afl->plot_prev_ce == afl->current_entry &&
|
||||
afl->plot_prev_qc == afl->queue_cycle &&
|
||||
afl->plot_prev_uc == afl->unique_crashes &&
|
||||
afl->plot_prev_uh == afl->unique_hangs &&
|
||||
afl->plot_prev_md == afl->max_depth)
|
||||
afl->plot_prev_md == afl->max_depth) ||
|
||||
unlikely(!afl->queue_cycle)) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
afl->plot_prev_qp = afl->queued_paths;
|
||||
afl->plot_prev_pf = afl->pending_favored;
|
||||
afl->plot_prev_pnf = afl->pending_not_fuzzed;
|
||||
@ -189,10 +193,10 @@ static void check_term_size(afl_state_t *afl) {
|
||||
|
||||
afl->term_too_small = 0;
|
||||
|
||||
if (ioctl(1, TIOCGWINSZ, &ws)) return;
|
||||
if (ioctl(1, TIOCGWINSZ, &ws)) { return; }
|
||||
|
||||
if (ws.ws_row == 0 || ws.ws_col == 0) return;
|
||||
if (ws.ws_row < 24 || ws.ws_col < 79) afl->term_too_small = 1;
|
||||
if (ws.ws_row == 0 || ws.ws_col == 0) { return; }
|
||||
if (ws.ws_row < 24 || ws.ws_col < 79) { afl->term_too_small = 1; }
|
||||
|
||||
}
|
||||
|
||||
@ -240,12 +244,15 @@ void show_stats(afl_state_t *afl) {
|
||||
/* If not enough time has passed since last UI update, bail out. */
|
||||
|
||||
if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
|
||||
!afl->force_ui_update)
|
||||
!afl->force_ui_update) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Check if we're past the 10 minute mark. */
|
||||
|
||||
if (cur_ms - afl->start_time > 10 * 60 * 1000) afl->run_over10m = 1;
|
||||
if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; }
|
||||
|
||||
/* Calculate smoothed exec speed stats. */
|
||||
|
||||
@ -262,9 +269,13 @@ void show_stats(afl_state_t *afl) {
|
||||
/* If there is a dramatic (5x+) jump in speed, reset the indicator
|
||||
more quickly. */
|
||||
|
||||
if (cur_avg * 5 < afl->stats_avg_exec || cur_avg / 5 > afl->stats_avg_exec)
|
||||
if (cur_avg * 5 < afl->stats_avg_exec ||
|
||||
cur_avg / 5 > afl->stats_avg_exec) {
|
||||
|
||||
afl->stats_avg_exec = cur_avg;
|
||||
|
||||
}
|
||||
|
||||
afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
|
||||
cur_avg * (1.0 / AVG_SMOOTHING);
|
||||
|
||||
@ -276,18 +287,23 @@ void show_stats(afl_state_t *afl) {
|
||||
/* Tell the callers when to contact us (as measured in execs). */
|
||||
|
||||
afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
|
||||
if (!afl->stats_update_freq) afl->stats_update_freq = 1;
|
||||
if (!afl->stats_update_freq) { afl->stats_update_freq = 1; }
|
||||
|
||||
/* Do some bitmap stats. */
|
||||
|
||||
t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
|
||||
t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.map_size;
|
||||
|
||||
if (likely(t_bytes) && unlikely(afl->var_byte_count))
|
||||
if (likely(t_bytes) && unlikely(afl->var_byte_count)) {
|
||||
|
||||
stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
stab_ratio = 100;
|
||||
|
||||
}
|
||||
|
||||
/* Roughly every minute, update fuzzer stats and save auto tokens. */
|
||||
|
||||
if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
|
||||
@ -311,19 +327,25 @@ void show_stats(afl_state_t *afl) {
|
||||
/* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
|
||||
|
||||
if (!afl->dumb_mode && afl->cycles_wo_finds > 100 &&
|
||||
!afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)
|
||||
!afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) {
|
||||
|
||||
afl->stop_soon = 2;
|
||||
|
||||
if (afl->total_crashes && afl->afl_env.afl_bench_until_crash)
|
||||
}
|
||||
|
||||
if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) {
|
||||
|
||||
afl->stop_soon = 2;
|
||||
|
||||
}
|
||||
|
||||
/* If we're not on TTY, bail out. */
|
||||
|
||||
if (afl->not_on_tty) return;
|
||||
if (afl->not_on_tty) { return; }
|
||||
|
||||
/* If we haven't started doing things, bail out. */
|
||||
|
||||
if (!afl->queue_cur) return;
|
||||
if (!afl->queue_cur) { return; }
|
||||
|
||||
/* Compute some mildly useful bitmap stats. */
|
||||
|
||||
@ -401,26 +423,35 @@ void show_stats(afl_state_t *afl) {
|
||||
u64 min_wo_finds = (cur_ms - afl->last_path_time) / 1000 / 60;
|
||||
|
||||
/* First queue cycle: don't stop now! */
|
||||
if (afl->queue_cycle == 1 || min_wo_finds < 15)
|
||||
if (afl->queue_cycle == 1 || min_wo_finds < 15) {
|
||||
|
||||
strcpy(tmp, cMGN);
|
||||
else
|
||||
|
||||
} else
|
||||
|
||||
/* Subsequent cycles, but we're still making finds. */
|
||||
if (afl->cycles_wo_finds < 25 || min_wo_finds < 30)
|
||||
if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) {
|
||||
|
||||
strcpy(tmp, cYEL);
|
||||
else
|
||||
|
||||
} else
|
||||
|
||||
/* No finds for a long time and no test cases to try. */
|
||||
if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed &&
|
||||
min_wo_finds > 120)
|
||||
min_wo_finds > 120) {
|
||||
|
||||
strcpy(tmp, cLGN);
|
||||
|
||||
/* Default: cautiously OK to stop? */
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
strcpy(tmp, cLBL);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u_stringify_time_diff(time_tmp, cur_ms, afl->start_time);
|
||||
SAYF(bV bSTOP " run time : " cRST "%-33s " bSTG bV bSTOP
|
||||
" cycles done : %s%-5s " bSTG bV "\n",
|
||||
@ -438,18 +469,20 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
} else {
|
||||
|
||||
if (afl->dumb_mode)
|
||||
if (afl->dumb_mode) {
|
||||
|
||||
SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST
|
||||
" (non-instrumented mode) ");
|
||||
|
||||
else
|
||||
} else {
|
||||
|
||||
SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD
|
||||
"(odd, check syntax!) ");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n",
|
||||
u_stringify_int(IB(0), afl->queued_paths));
|
||||
|
||||
@ -604,7 +637,8 @@ void show_stats(afl_state_t *afl) {
|
||||
" levels : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, u_stringify_int(IB(0), afl->max_depth));
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
if (!afl->skip_deterministic) {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
|
||||
@ -613,11 +647,14 @@ void show_stats(afl_state_t *afl) {
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
|
||||
|
||||
}
|
||||
|
||||
SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP
|
||||
" pending : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
if (!afl->skip_deterministic) {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
|
||||
@ -626,11 +663,14 @@ void show_stats(afl_state_t *afl) {
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
|
||||
|
||||
}
|
||||
|
||||
SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
|
||||
" pend fav : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, u_stringify_int(IB(0), afl->pending_favored));
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
if (!afl->skip_deterministic) {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
|
||||
@ -639,11 +679,14 @@ void show_stats(afl_state_t *afl) {
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
|
||||
|
||||
}
|
||||
|
||||
SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP
|
||||
" own finds : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, u_stringify_int(IB(0), afl->queued_discovered));
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
if (!afl->skip_deterministic) {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
|
||||
@ -652,6 +695,8 @@ void show_stats(afl_state_t *afl) {
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
|
||||
|
||||
}
|
||||
|
||||
SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP
|
||||
" imported : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp,
|
||||
@ -668,11 +713,16 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
|
||||
if (t_bytes)
|
||||
if (t_bytes) {
|
||||
|
||||
sprintf(tmp, "%0.02f%%", stab_ratio);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
strcpy(tmp, "n/a");
|
||||
|
||||
}
|
||||
|
||||
SAYF(" stability : %s%-10s" bSTG bV "\n",
|
||||
(stab_ratio < 85 && afl->var_byte_count > 40)
|
||||
? cLRD
|
||||
@ -768,14 +818,17 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
/* If we could still run one or more processes, use green. */
|
||||
|
||||
if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count)
|
||||
if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) {
|
||||
|
||||
cpu_color = cLGN;
|
||||
|
||||
}
|
||||
|
||||
/* If we're clearly oversubscribed, use red. */
|
||||
|
||||
if (!afl->no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD;
|
||||
if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; }
|
||||
|
||||
if (afl->fsrv.snapshot) spacing = snap;
|
||||
if (afl->fsrv.snapshot) { spacing = snap; }
|
||||
|
||||
#ifdef HAVE_AFFINITY
|
||||
|
||||
@ -798,10 +851,12 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
#endif /* ^HAVE_AFFINITY */
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
SAYF("\r");
|
||||
|
||||
}
|
||||
|
||||
/* Last line */
|
||||
SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
|
||||
|
||||
@ -828,17 +883,21 @@ void show_init_stats(afl_state_t *afl) {
|
||||
u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX];
|
||||
#define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)])
|
||||
|
||||
if (afl->total_cal_cycles) avg_us = afl->total_cal_us / afl->total_cal_cycles;
|
||||
if (afl->total_cal_cycles) {
|
||||
|
||||
avg_us = afl->total_cal_us / afl->total_cal_cycles;
|
||||
|
||||
}
|
||||
|
||||
while (q) {
|
||||
|
||||
if (!min_us || q->exec_us < min_us) min_us = q->exec_us;
|
||||
if (q->exec_us > max_us) max_us = q->exec_us;
|
||||
if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; }
|
||||
if (q->exec_us > max_us) { max_us = q->exec_us; }
|
||||
|
||||
if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size;
|
||||
if (q->bitmap_size > max_bits) max_bits = q->bitmap_size;
|
||||
if (!min_bits || q->bitmap_size < min_bits) { min_bits = q->bitmap_size; }
|
||||
if (q->bitmap_size > max_bits) { max_bits = q->bitmap_size; }
|
||||
|
||||
if (q->len > max_len) max_len = q->len;
|
||||
if (q->len > max_len) { max_len = q->len; }
|
||||
|
||||
q = q->next;
|
||||
|
||||
@ -846,40 +905,63 @@ void show_init_stats(afl_state_t *afl) {
|
||||
|
||||
SAYF("\n");
|
||||
|
||||
if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000))
|
||||
if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) {
|
||||
|
||||
WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
|
||||
doc_path);
|
||||
|
||||
}
|
||||
|
||||
/* Let's keep things moving with slow binaries. */
|
||||
|
||||
if (avg_us > 50000)
|
||||
if (avg_us > 50000) {
|
||||
|
||||
afl->havoc_div = 10; /* 0-19 execs/sec */
|
||||
else if (avg_us > 20000)
|
||||
|
||||
} else if (avg_us > 20000) {
|
||||
|
||||
afl->havoc_div = 5; /* 20-49 execs/sec */
|
||||
else if (avg_us > 10000)
|
||||
|
||||
} else if (avg_us > 10000) {
|
||||
|
||||
afl->havoc_div = 2; /* 50-100 execs/sec */
|
||||
|
||||
}
|
||||
|
||||
if (!afl->resuming_fuzz) {
|
||||
|
||||
if (max_len > 50 * 1024)
|
||||
if (max_len > 50 * 1024) {
|
||||
|
||||
WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
|
||||
stringify_mem_size(IB(0), max_len), doc_path);
|
||||
else if (max_len > 10 * 1024)
|
||||
|
||||
} else if (max_len > 10 * 1024) {
|
||||
|
||||
WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
|
||||
stringify_mem_size(IB(0), max_len), doc_path);
|
||||
|
||||
if (afl->useless_at_start && !afl->in_bitmap)
|
||||
}
|
||||
|
||||
if (afl->useless_at_start && !afl->in_bitmap) {
|
||||
|
||||
WARNF(cLRD "Some test cases look useless. Consider using a smaller set.");
|
||||
|
||||
if (afl->queued_paths > 100)
|
||||
}
|
||||
|
||||
if (afl->queued_paths > 100) {
|
||||
|
||||
WARNF(cLRD
|
||||
"You probably have far too many input files! Consider trimming "
|
||||
"down.");
|
||||
else if (afl->queued_paths > 20)
|
||||
|
||||
} else if (afl->queued_paths > 20) {
|
||||
|
||||
WARNF("You have lots of input files; try starting small.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OKF("Here are some useful stats:\n\n"
|
||||
|
||||
cGRA " Test case count : " cRST
|
||||
@ -902,20 +984,30 @@ void show_init_stats(afl_state_t *afl) {
|
||||
random scheduler jitter is less likely to have any impact, and because
|
||||
our patience is wearing thin =) */
|
||||
|
||||
if (avg_us > 50000)
|
||||
if (avg_us > 50000) {
|
||||
|
||||
afl->fsrv.exec_tmout = avg_us * 2 / 1000;
|
||||
else if (avg_us > 10000)
|
||||
|
||||
} else if (avg_us > 10000) {
|
||||
|
||||
afl->fsrv.exec_tmout = avg_us * 3 / 1000;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
afl->fsrv.exec_tmout = avg_us * 5 / 1000;
|
||||
|
||||
}
|
||||
|
||||
afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000);
|
||||
afl->fsrv.exec_tmout =
|
||||
(afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND;
|
||||
|
||||
if (afl->fsrv.exec_tmout > EXEC_TIMEOUT)
|
||||
if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) {
|
||||
|
||||
afl->fsrv.exec_tmout = EXEC_TIMEOUT;
|
||||
|
||||
}
|
||||
|
||||
ACTF("No -t option specified, so I'll use exec timeout of %u ms.",
|
||||
afl->fsrv.exec_tmout);
|
||||
|
||||
@ -931,9 +1023,12 @@ void show_init_stats(afl_state_t *afl) {
|
||||
/* In dumb mode, re-running every timing out test case with a generous time
|
||||
limit is very expensive, so let's select a more conservative default. */
|
||||
|
||||
if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout))
|
||||
if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) {
|
||||
|
||||
afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
|
||||
|
||||
}
|
||||
|
||||
OKF("All set and ready to roll!");
|
||||
#undef IB
|
||||
|
||||
|
512
src/afl-fuzz.c
512
src/afl-fuzz.c
File diff suppressed because it is too large
Load Diff
@ -128,11 +128,16 @@ static void edit_params(u32 argc, char **argv) {
|
||||
cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
|
||||
|
||||
name = strrchr(argv[0], '/');
|
||||
if (!name)
|
||||
if (!name) {
|
||||
|
||||
name = argv[0];
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
++name;
|
||||
|
||||
}
|
||||
|
||||
if (!strncmp(name, "afl-clang", 9)) {
|
||||
|
||||
clang_mode = 1;
|
||||
@ -211,7 +216,7 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
if (!strncmp(cur, "-B", 2)) {
|
||||
|
||||
if (!be_quiet) WARNF("-B is already set, overriding");
|
||||
if (!be_quiet) { WARNF("-B is already set, overriding"); }
|
||||
|
||||
if (!cur[2] && argc > 1) {
|
||||
|
||||
@ -224,18 +229,22 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (!strcmp(cur, "-integrated-as")) continue;
|
||||
if (!strcmp(cur, "-integrated-as")) { continue; }
|
||||
|
||||
if (!strcmp(cur, "-pipe")) continue;
|
||||
if (!strcmp(cur, "-pipe")) { continue; }
|
||||
|
||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
||||
if (!strcmp(cur, "-m32")) m32_set = 1;
|
||||
#endif
|
||||
|
||||
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
|
||||
if (!strcmp(cur, "-fsanitize=address") ||
|
||||
!strcmp(cur, "-fsanitize=memory")) {
|
||||
|
||||
asan_set = 1;
|
||||
|
||||
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
|
||||
}
|
||||
|
||||
if (strstr(cur, "FORTIFY_SOURCE")) { fortify_set = 1; }
|
||||
|
||||
cc_params[cc_par_cnt++] = cur;
|
||||
|
||||
@ -244,13 +253,13 @@ static void edit_params(u32 argc, char **argv) {
|
||||
cc_params[cc_par_cnt++] = "-B";
|
||||
cc_params[cc_par_cnt++] = as_path;
|
||||
|
||||
if (clang_mode) cc_params[cc_par_cnt++] = "-no-integrated-as";
|
||||
if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
|
||||
|
||||
if (getenv("AFL_HARDEN")) {
|
||||
|
||||
cc_params[cc_par_cnt++] = "-fstack-protector-all";
|
||||
|
||||
if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
|
||||
if (!fortify_set) { cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; }
|
||||
|
||||
}
|
||||
|
||||
@ -262,21 +271,35 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
} else if (getenv("AFL_USE_ASAN")) {
|
||||
|
||||
if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive");
|
||||
if (getenv("AFL_USE_MSAN")) {
|
||||
|
||||
FATAL("ASAN and MSAN are mutually exclusive");
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_HARDEN")) {
|
||||
|
||||
if (getenv("AFL_HARDEN"))
|
||||
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
|
||||
|
||||
}
|
||||
|
||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
||||
cc_params[cc_par_cnt++] = "-fsanitize=address";
|
||||
|
||||
} else if (getenv("AFL_USE_MSAN")) {
|
||||
|
||||
if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive");
|
||||
if (getenv("AFL_USE_ASAN")) {
|
||||
|
||||
FATAL("ASAN and MSAN are mutually exclusive");
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_HARDEN")) {
|
||||
|
||||
if (getenv("AFL_HARDEN"))
|
||||
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
|
||||
|
||||
}
|
||||
|
||||
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
|
||||
cc_params[cc_par_cnt++] = "-fsanitize=memory";
|
||||
|
||||
@ -386,10 +409,12 @@ int main(int argc, char **argv) {
|
||||
"afl-gcc is deprecated, llvm_mode is much faster and has more "
|
||||
"options\n");
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
|
||||
SAYF(
|
||||
@ -411,6 +436,19 @@ int main(int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
u8 *ptr;
|
||||
if (!be_quiet &&
|
||||
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
|
||||
|
||||
u32 map_size = atoi(ptr);
|
||||
if (map_size != MAP_SIZE) {
|
||||
|
||||
FATAL("AFL_MAP_SIZE is not supported by afl-gcc");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
find_as(argv[0]);
|
||||
|
||||
edit_params(argc, argv);
|
||||
|
@ -102,8 +102,12 @@ repeat_loop:
|
||||
|
||||
v1 = CTEST_BUSY_CYCLES;
|
||||
|
||||
while (v1--)
|
||||
while (v1--) {
|
||||
|
||||
v2++;
|
||||
|
||||
}
|
||||
|
||||
sched_yield();
|
||||
|
||||
en_t = get_cur_time_us();
|
||||
@ -154,7 +158,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
s32 fr = fork();
|
||||
|
||||
if (fr < 0) PFATAL("fork failed");
|
||||
if (fr < 0) { PFATAL("fork failed"); }
|
||||
|
||||
if (!fr) {
|
||||
|
||||
@ -192,8 +196,12 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
if (sched_setaffinity(0, sizeof(c), &c))
|
||||
if (sched_setaffinity(0, sizeof(c), &c)) {
|
||||
|
||||
PFATAL("sched_setaffinity failed for cpu %d", i);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
util_perc = measure_preemption(CTEST_CORE_TRG_MS);
|
||||
@ -221,10 +229,10 @@ int main(int argc, char **argv) {
|
||||
for (i = 0; i < cpu_cnt; i++) {
|
||||
|
||||
int ret;
|
||||
if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed");
|
||||
if (waitpid(-1, &ret, 0) < 0) { PFATAL("waitpid failed"); }
|
||||
|
||||
if (WEXITSTATUS(ret) == 0) idle_cpus++;
|
||||
if (WEXITSTATUS(ret) <= 1) maybe_cpus++;
|
||||
if (WEXITSTATUS(ret) == 0) { idle_cpus++; }
|
||||
if (WEXITSTATUS(ret) <= 1) { maybe_cpus++; }
|
||||
|
||||
}
|
||||
|
||||
|
@ -66,13 +66,12 @@ static list_t shm_list = {.element_prealloc_count = 0};
|
||||
|
||||
void afl_shm_deinit(sharedmem_t *shm) {
|
||||
|
||||
// TODO: clang reports a potential UAF in this function/makro(?)
|
||||
list_remove(&shm_list, shm);
|
||||
|
||||
#ifdef USEMMAP
|
||||
if (shm->map != NULL) {
|
||||
|
||||
munmap(shm->map, shm->size_alloc);
|
||||
munmap(shm->map, shm->map_size);
|
||||
shm->map = NULL;
|
||||
|
||||
}
|
||||
@ -86,7 +85,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
|
||||
|
||||
#else
|
||||
shmctl(shm->shm_id, IPC_RMID, NULL);
|
||||
if (shm->cmplog_mode) shmctl(shm->cmplog_shm_id, IPC_RMID, NULL);
|
||||
if (shm->cmplog_mode) { shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); }
|
||||
#endif
|
||||
|
||||
shm->map = NULL;
|
||||
@ -99,7 +98,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
|
||||
|
||||
u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
|
||||
|
||||
shm->size_alloc = shm->size_used = map_size;
|
||||
shm->map_size = map_size;
|
||||
|
||||
shm->map = NULL;
|
||||
|
||||
@ -152,14 +151,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
|
||||
|
||||
shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600);
|
||||
|
||||
if (shm->shm_id < 0) PFATAL("shmget() failed");
|
||||
if (shm->shm_id < 0) { PFATAL("shmget() failed"); }
|
||||
|
||||
if (shm->cmplog_mode) {
|
||||
|
||||
shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map),
|
||||
IPC_CREAT | IPC_EXCL | 0600);
|
||||
|
||||
if (shm->cmplog_shm_id < 0) PFATAL("shmget() failed");
|
||||
if (shm->cmplog_shm_id < 0) { PFATAL("shmget() failed"); }
|
||||
|
||||
}
|
||||
|
||||
@ -170,7 +169,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
|
||||
fork server commands. This should be replaced with better auto-detection
|
||||
later on, perhaps? */
|
||||
|
||||
if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1);
|
||||
if (!dumb_mode) { setenv(SHM_ENV_VAR, shm_str, 1); }
|
||||
|
||||
ck_free(shm_str);
|
||||
|
||||
@ -178,7 +177,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
|
||||
|
||||
shm_str = alloc_printf("%d", shm->cmplog_shm_id);
|
||||
|
||||
if (!dumb_mode) setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1);
|
||||
if (!dumb_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); }
|
||||
|
||||
ck_free(shm_str);
|
||||
|
||||
@ -186,13 +185,17 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
|
||||
|
||||
shm->map = shmat(shm->shm_id, NULL, 0);
|
||||
|
||||
if (shm->map == (void *)-1 || !shm->map) PFATAL("shmat() failed");
|
||||
if (shm->map == (void *)-1 || !shm->map) { PFATAL("shmat() failed"); }
|
||||
|
||||
if (shm->cmplog_mode) {
|
||||
|
||||
shm->cmp_map = shmat(shm->cmplog_shm_id, NULL, 0);
|
||||
|
||||
if (shm->cmp_map == (void *)-1 || !shm->cmp_map) PFATAL("shmat() failed");
|
||||
if (shm->cmp_map == (void *)-1 || !shm->cmp_map) {
|
||||
|
||||
PFATAL("shmat() failed");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
@ -72,6 +73,8 @@ static u32 total, highest; /* tuple content information */
|
||||
static u32 in_len, /* Input data length */
|
||||
arg_offset; /* Total number of execs */
|
||||
|
||||
static u32 map_size = MAP_SIZE;
|
||||
|
||||
static u8 quiet_mode, /* Hide non-essential messages? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
raw_instr_output, /* Do not apply AFL filters */
|
||||
@ -112,13 +115,13 @@ static void classify_counts(afl_forkserver_t *fsrv) {
|
||||
u8 * mem = fsrv->trace_bits;
|
||||
const u8 *map = binary_mode ? count_class_binary : count_class_human;
|
||||
|
||||
u32 i = MAP_SIZE;
|
||||
u32 i = map_size;
|
||||
|
||||
if (edges_only) {
|
||||
|
||||
while (i--) {
|
||||
|
||||
if (*mem) *mem = 1;
|
||||
if (*mem) { *mem = 1; }
|
||||
mem++;
|
||||
|
||||
}
|
||||
@ -140,7 +143,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
static void at_exit_handler(void) {
|
||||
|
||||
if (stdin_file) unlink(stdin_file);
|
||||
if (stdin_file) { unlink(stdin_file); }
|
||||
|
||||
}
|
||||
|
||||
@ -154,60 +157,67 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
||||
u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"),
|
||||
caa = !!getenv("AFL_CMIN_ALLOW_ANY");
|
||||
|
||||
if (!outfile) { FATAL("Output filename not set (Bug in AFL++?)"); }
|
||||
|
||||
if (!strncmp(outfile, "/dev/", 5)) {
|
||||
|
||||
fd = open(outfile, O_WRONLY);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", out_file);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", out_file); }
|
||||
|
||||
} else if (!strcmp(outfile, "-")) {
|
||||
|
||||
fd = dup(1);
|
||||
if (fd < 0) PFATAL("Unable to open stdout");
|
||||
if (fd < 0) { PFATAL("Unable to open stdout"); }
|
||||
|
||||
} else {
|
||||
|
||||
unlink(outfile); /* Ignore errors */
|
||||
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", outfile);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", outfile); }
|
||||
|
||||
}
|
||||
|
||||
if (binary_mode) {
|
||||
|
||||
for (i = 0; i < MAP_SIZE; i++)
|
||||
if (fsrv->trace_bits[i]) ret++;
|
||||
for (i = 0; i < map_size; i++) {
|
||||
|
||||
ck_write(fd, fsrv->trace_bits, MAP_SIZE, outfile);
|
||||
if (fsrv->trace_bits[i]) { ret++; }
|
||||
|
||||
}
|
||||
|
||||
ck_write(fd, fsrv->trace_bits, map_size, outfile);
|
||||
close(fd);
|
||||
|
||||
} else {
|
||||
|
||||
FILE *f = fdopen(fd, "w");
|
||||
|
||||
if (!f) PFATAL("fdopen() failed");
|
||||
if (!f) { PFATAL("fdopen() failed"); }
|
||||
|
||||
for (i = 0; i < MAP_SIZE; i++) {
|
||||
for (i = 0; i < map_size; i++) {
|
||||
|
||||
if (!fsrv->trace_bits[i]) continue;
|
||||
if (!fsrv->trace_bits[i]) { continue; }
|
||||
ret++;
|
||||
|
||||
total += fsrv->trace_bits[i];
|
||||
if (highest < fsrv->trace_bits[i]) highest = fsrv->trace_bits[i];
|
||||
if (highest < fsrv->trace_bits[i]) { highest = fsrv->trace_bits[i]; }
|
||||
|
||||
if (cmin_mode) {
|
||||
|
||||
if (fsrv->last_run_timed_out) break;
|
||||
if (!caa && child_crashed != cco) break;
|
||||
if (fsrv->last_run_timed_out) { break; }
|
||||
if (!caa && child_crashed != cco) { break; }
|
||||
|
||||
fprintf(f, "%u%u\n", fsrv->trace_bits[i], i);
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
fprintf(f, "%06u:%u\n", i, fsrv->trace_bits[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
}
|
||||
@ -218,8 +228,8 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
||||
|
||||
/* Execute target application. */
|
||||
|
||||
static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
|
||||
u32 len) {
|
||||
static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv,
|
||||
u8 *mem, u32 len) {
|
||||
|
||||
afl_fsrv_write_to_testcase(fsrv, mem, len);
|
||||
|
||||
@ -248,11 +258,14 @@ static u32 read_file(u8 *in_file) {
|
||||
struct stat st;
|
||||
s32 fd = open(in_file, O_RDONLY);
|
||||
|
||||
if (fd < 0) WARNF("Unable to open '%s'", in_file);
|
||||
if (fd < 0) { WARNF("Unable to open '%s'", in_file); }
|
||||
|
||||
if (fstat(fd, &st) || !st.st_size) {
|
||||
|
||||
if (fstat(fd, &st) || !st.st_size)
|
||||
WARNF("Zero-sized input file '%s'.", in_file);
|
||||
|
||||
}
|
||||
|
||||
in_len = st.st_size;
|
||||
in_data = ck_alloc_nozero(in_len);
|
||||
|
||||
@ -273,13 +286,13 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
static struct itimerval it;
|
||||
int status = 0;
|
||||
|
||||
if (!quiet_mode) SAYF("-- Program output begins --\n" cRST);
|
||||
if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
|
||||
|
||||
MEM_BARRIER();
|
||||
|
||||
fsrv->child_pid = fork();
|
||||
|
||||
if (fsrv->child_pid < 0) PFATAL("fork() failed");
|
||||
if (fsrv->child_pid < 0) { PFATAL("fork() failed"); }
|
||||
|
||||
if (!fsrv->child_pid) {
|
||||
|
||||
@ -316,14 +329,19 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (!keep_cores)
|
||||
if (!keep_cores) {
|
||||
|
||||
r.rlim_max = r.rlim_cur = 0;
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
r.rlim_max = r.rlim_cur = RLIM_INFINITY;
|
||||
|
||||
}
|
||||
|
||||
setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
|
||||
|
||||
if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0);
|
||||
if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); }
|
||||
|
||||
setsid();
|
||||
|
||||
@ -346,7 +364,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
setitimer(ITIMER_REAL, &it, NULL);
|
||||
|
||||
if (waitpid(fsrv->child_pid, &status, 0) <= 0) FATAL("waitpid() failed");
|
||||
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
|
||||
|
||||
fsrv->child_pid = 0;
|
||||
it.it_value.tv_sec = 0;
|
||||
@ -357,28 +375,41 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
/* Clean up bitmap, analyze exit condition, etc. */
|
||||
|
||||
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG)
|
||||
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) {
|
||||
|
||||
FATAL("Unable to execute '%s'", argv[0]);
|
||||
|
||||
}
|
||||
|
||||
classify_counts(fsrv);
|
||||
|
||||
if (!quiet_mode) SAYF(cRST "-- Program output ends --\n");
|
||||
if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); }
|
||||
|
||||
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) {
|
||||
|
||||
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status))
|
||||
child_crashed = 1;
|
||||
|
||||
}
|
||||
|
||||
if (!quiet_mode) {
|
||||
|
||||
if (fsrv->last_run_timed_out)
|
||||
if (fsrv->last_run_timed_out) {
|
||||
|
||||
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||
else if (stop_soon)
|
||||
|
||||
} else if (stop_soon) {
|
||||
|
||||
SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
|
||||
else if (child_crashed)
|
||||
|
||||
} else if (child_crashed) {
|
||||
|
||||
SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST,
|
||||
WTERMSIG(status));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Handle Ctrl-C and the like. */
|
||||
@ -418,20 +449,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
if (afl_preload[i] == ',') {
|
||||
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
}
|
||||
|
||||
if (qemu_preload) {
|
||||
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
qemu_preload, afl_preload, afl_preload);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
afl_preload, afl_preload);
|
||||
|
||||
}
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
@ -486,11 +525,9 @@ static void usage(u8 *argv0) {
|
||||
"\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
|
||||
|
||||
"Required parameters:\n"
|
||||
|
||||
" -o file - file to write the trace data to\n\n"
|
||||
|
||||
"Execution control settings:\n"
|
||||
|
||||
" -t msec - timeout for each run (none)\n"
|
||||
" -m megs - memory limit for child process (%d MB)\n"
|
||||
" -Q - use binary-only instrumentation (QEMU mode)\n"
|
||||
@ -498,9 +535,7 @@ static void usage(u8 *argv0) {
|
||||
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
|
||||
" (Not necessary, here for consistency with other afl-* "
|
||||
"tools)\n\n"
|
||||
|
||||
"Other settings:\n"
|
||||
|
||||
" -i dir - process all files in this directory, -o must be a "
|
||||
"directory\n"
|
||||
" and each bitmap will be written there individually.\n"
|
||||
@ -513,13 +548,16 @@ static void usage(u8 *argv0) {
|
||||
"For additional help, consult %s/README.md.\n\n"
|
||||
|
||||
"Environment variables used:\n"
|
||||
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
|
||||
"AFL_DEBUG: enable extra developer output\n"
|
||||
"AFL_QUIET: do not print extra informational output"
|
||||
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
|
||||
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
|
||||
"inputs\n"
|
||||
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
|
||||
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\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_QUIET: do not print extra informational output",
|
||||
argv0, MEM_LIMIT, doc_path);
|
||||
|
||||
exit(1);
|
||||
@ -542,23 +580,25 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
afl_forkserver_t fsrv_var = {0};
|
||||
afl_forkserver_t *fsrv = &fsrv_var;
|
||||
afl_fsrv_init(fsrv);
|
||||
map_size = get_map_size();
|
||||
fsrv->map_size = map_size;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
||||
if (getenv("AFL_QUIET") != NULL) be_quiet = 1;
|
||||
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
|
||||
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0)
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'i':
|
||||
if (in_dir) FATAL("Multiple -i options not supported");
|
||||
if (in_dir) { FATAL("Multiple -i options not supported"); }
|
||||
in_dir = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
|
||||
if (out_file) FATAL("Multiple -o options not supported");
|
||||
if (out_file) { FATAL("Multiple -o options not supported"); }
|
||||
out_file = optarg;
|
||||
break;
|
||||
|
||||
@ -566,10 +606,10 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
u8 suffix = 'M';
|
||||
|
||||
if (mem_limit_given) FATAL("Multiple -m options not supported");
|
||||
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
|
||||
mem_limit_given = 1;
|
||||
|
||||
if (!optarg) FATAL("Wrong usage of -m");
|
||||
if (!optarg) { FATAL("Wrong usage of -m"); }
|
||||
|
||||
if (!strcmp(optarg, "none")) {
|
||||
|
||||
@ -579,27 +619,41 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
|
||||
optarg[0] == '-')
|
||||
optarg[0] == '-') {
|
||||
|
||||
FATAL("Bad syntax used for -m");
|
||||
|
||||
switch (suffix) {
|
||||
|
||||
case 'T': fsrv->mem_limit *= 1024 * 1024; break;
|
||||
case 'G': fsrv->mem_limit *= 1024; break;
|
||||
case 'k': fsrv->mem_limit /= 1024; break;
|
||||
case 'M': break;
|
||||
|
||||
default: FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m");
|
||||
switch (suffix) {
|
||||
|
||||
case 'T':
|
||||
fsrv->mem_limit *= 1024 * 1024;
|
||||
break;
|
||||
case 'G':
|
||||
fsrv->mem_limit *= 1024;
|
||||
break;
|
||||
case 'k':
|
||||
fsrv->mem_limit /= 1024;
|
||||
break;
|
||||
case 'M':
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
|
||||
|
||||
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
|
||||
|
||||
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000)
|
||||
FATAL("Value of -m out of range on 32-bit systems");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'f': // only in here to avoid a compiler warning for use_stdin
|
||||
@ -611,32 +665,35 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
case 't':
|
||||
|
||||
if (timeout_given) FATAL("Multiple -t options not supported");
|
||||
if (timeout_given) { FATAL("Multiple -t options not supported"); }
|
||||
timeout_given = 1;
|
||||
|
||||
if (!optarg) FATAL("Wrong usage of -t");
|
||||
if (!optarg) { FATAL("Wrong usage of -t"); }
|
||||
|
||||
if (strcmp(optarg, "none")) {
|
||||
|
||||
fsrv->exec_tmout = atoi(optarg);
|
||||
|
||||
if (fsrv->exec_tmout < 20 || optarg[0] == '-')
|
||||
if (fsrv->exec_tmout < 20 || optarg[0] == '-') {
|
||||
|
||||
FATAL("Dangerously low value of -t");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
|
||||
if (edges_only) FATAL("Multiple -e options not supported");
|
||||
if (raw_instr_output) FATAL("-e and -r are mutually exclusive");
|
||||
if (edges_only) { FATAL("Multiple -e options not supported"); }
|
||||
if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); }
|
||||
edges_only = 1;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
|
||||
if (quiet_mode) FATAL("Multiple -q options not supported");
|
||||
if (quiet_mode) { FATAL("Multiple -q options not supported"); }
|
||||
quiet_mode = 1;
|
||||
break;
|
||||
|
||||
@ -656,27 +713,27 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
case 'Q':
|
||||
|
||||
if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported");
|
||||
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU;
|
||||
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
|
||||
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
|
||||
|
||||
fsrv->qemu_mode = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
|
||||
if (unicorn_mode) FATAL("Multiple -U options not supported");
|
||||
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN;
|
||||
if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
|
||||
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
|
||||
|
||||
unicorn_mode = 1;
|
||||
break;
|
||||
|
||||
case 'W': /* Wine+QEMU mode */
|
||||
|
||||
if (use_wine) FATAL("Multiple -W options not supported");
|
||||
if (use_wine) { FATAL("Multiple -W options not supported"); }
|
||||
fsrv->qemu_mode = 1;
|
||||
use_wine = 1;
|
||||
|
||||
if (!mem_limit_given) fsrv->mem_limit = 0;
|
||||
if (!mem_limit_given) { fsrv->mem_limit = 0; }
|
||||
|
||||
break;
|
||||
|
||||
@ -690,14 +747,14 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
case 'c':
|
||||
|
||||
if (keep_cores) FATAL("Multiple -c options not supported");
|
||||
if (keep_cores) { FATAL("Multiple -c options not supported"); }
|
||||
keep_cores = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
|
||||
if (raw_instr_output) FATAL("Multiple -r options not supported");
|
||||
if (edges_only) FATAL("-e and -r are mutually exclusive");
|
||||
if (raw_instr_output) { FATAL("Multiple -r options not supported"); }
|
||||
if (edges_only) { FATAL("-e and -r are mutually exclusive"); }
|
||||
raw_instr_output = 1;
|
||||
break;
|
||||
|
||||
@ -706,16 +763,19 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
return -1;
|
||||
break;
|
||||
|
||||
default: usage(argv[0]);
|
||||
default:
|
||||
usage(argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc || !out_file) usage(argv[0]);
|
||||
}
|
||||
|
||||
if (optind == argc || !out_file) { usage(argv[0]); }
|
||||
|
||||
check_environment_vars(envp);
|
||||
|
||||
sharedmem_t shm = {0};
|
||||
fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0);
|
||||
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||
setup_signal_handlers();
|
||||
|
||||
set_up_environment(fsrv);
|
||||
@ -731,7 +791,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (in_dir) {
|
||||
|
||||
if (at_file) PFATAL("Options -A and -i are mutually exclusive");
|
||||
if (at_file) { PFATAL("Options -A and -i are mutually exclusive"); }
|
||||
detect_file_args(argv + optind, "", &fsrv->use_stdin);
|
||||
|
||||
} else {
|
||||
@ -740,22 +800,32 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++)
|
||||
if (strcmp(argv[i], "@@") == 0) arg_offset = i;
|
||||
for (i = optind; i < argc; i++) {
|
||||
|
||||
if (strcmp(argv[i], "@@") == 0) { arg_offset = i; }
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->qemu_mode) {
|
||||
|
||||
if (use_wine)
|
||||
if (use_wine) {
|
||||
|
||||
use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind,
|
||||
argv + optind);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind,
|
||||
argv + optind);
|
||||
|
||||
} else
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
use_argv = argv + optind;
|
||||
|
||||
}
|
||||
|
||||
if (in_dir) {
|
||||
|
||||
DIR * dir_in, *dir_out;
|
||||
@ -767,20 +837,30 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
#endif
|
||||
|
||||
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
||||
if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null");
|
||||
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||
|
||||
if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir);
|
||||
if (!(dir_in = opendir(in_dir))) {
|
||||
|
||||
PFATAL("cannot open directory %s", in_dir);
|
||||
|
||||
}
|
||||
|
||||
if (!(dir_out = opendir(out_file))) {
|
||||
|
||||
if (mkdir(out_file, 0700)) {
|
||||
|
||||
if (!(dir_out = opendir(out_file)))
|
||||
if (mkdir(out_file, 0700))
|
||||
PFATAL("cannot create output directory %s", out_file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u8 *use_dir = ".";
|
||||
|
||||
if (access(use_dir, R_OK | W_OK | X_OK)) {
|
||||
|
||||
use_dir = get_afl_env("TMPDIR");
|
||||
if (!use_dir) use_dir = "/tmp";
|
||||
if (!use_dir) { use_dir = "/tmp"; }
|
||||
|
||||
}
|
||||
|
||||
@ -788,7 +868,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
unlink(stdin_file);
|
||||
atexit(at_exit_handler);
|
||||
fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file);
|
||||
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
|
||||
|
||||
if (arg_offset && argv[arg_offset] != stdin_file) {
|
||||
|
||||
@ -801,8 +881,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
int i = optind;
|
||||
SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
|
||||
while (argv[i] != NULL)
|
||||
while (argv[i] != NULL) {
|
||||
|
||||
SAYF(" \"%s\"", argv[i++]);
|
||||
|
||||
}
|
||||
|
||||
SAYF("\n");
|
||||
SAYF(cMGN "[D]" cRST " %d - %d = %d, %s\n", arg_offset, optind,
|
||||
arg_offset - optind, infile);
|
||||
@ -814,11 +898,19 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
while (done == 0 && (dir_ent = readdir(dir_in))) {
|
||||
|
||||
if (dir_ent->d_name[0] == '.')
|
||||
if (dir_ent->d_name[0] == '.') {
|
||||
|
||||
continue; // skip anything that starts with '.'
|
||||
|
||||
}
|
||||
|
||||
#if defined(DT_REG) /* Posix and Solaris do not know d_type and DT_REG */
|
||||
if (dir_ent->d_type != DT_REG) continue; // only regular files
|
||||
if (dir_ent->d_type != DT_REG) {
|
||||
|
||||
continue; // only regular files
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name);
|
||||
@ -839,10 +931,10 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (!quiet_mode) OKF("Processed %llu input files.", fsrv->total_execs);
|
||||
if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
|
||||
|
||||
closedir(dir_in);
|
||||
if (dir_out) closedir(dir_out);
|
||||
if (dir_out) { closedir(dir_out); }
|
||||
|
||||
} else {
|
||||
|
||||
@ -853,7 +945,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (!quiet_mode) {
|
||||
|
||||
if (!tcnt) FATAL("No instrumentation detected" cRST);
|
||||
if (!tcnt) { FATAL("No instrumentation detected" cRST); }
|
||||
OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST,
|
||||
tcnt, highest, total, out_file);
|
||||
|
||||
@ -871,12 +963,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
u32 ret = child_crashed * 2 + fsrv->last_run_timed_out;
|
||||
|
||||
if (fsrv->target_path) ck_free(fsrv->target_path);
|
||||
if (fsrv->target_path) { ck_free(fsrv->target_path); }
|
||||
|
||||
afl_fsrv_deinit(fsrv);
|
||||
if (stdin_file) ck_free(stdin_file);
|
||||
if (stdin_file) { ck_free(stdin_file); }
|
||||
|
||||
argv_cpy_free(argv);
|
||||
if (fsrv->qemu_mode) { free(use_argv[2]); }
|
||||
|
||||
exit(ret);
|
||||
|
||||
|
285
src/afl-tmin.c
285
src/afl-tmin.c
@ -70,7 +70,8 @@ static u32 in_len, /* Input data length */
|
||||
orig_cksum, /* Original checksum */
|
||||
missed_hangs, /* Misses due to hangs */
|
||||
missed_crashes, /* Misses due to crashes */
|
||||
missed_paths; /* Misses due to exec path diffs */
|
||||
missed_paths, /* Misses due to exec path diffs */
|
||||
map_size = MAP_SIZE;
|
||||
|
||||
static u8 crash_mode, /* Crash-centric mode? */
|
||||
hang_mode, /* Minimize as long as it hangs */
|
||||
@ -105,9 +106,9 @@ static const u8 count_class_lookup[256] = {
|
||||
|
||||
static void apply_mask(u32 *mem, u32 *mask) {
|
||||
|
||||
u32 i = (MAP_SIZE >> 2);
|
||||
u32 i = (map_size >> 2);
|
||||
|
||||
if (!mask) return;
|
||||
if (!mask) { return; }
|
||||
|
||||
while (i--) {
|
||||
|
||||
@ -122,13 +123,13 @@ static void apply_mask(u32 *mem, u32 *mask) {
|
||||
static void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
u8 *mem = fsrv->trace_bits;
|
||||
u32 i = MAP_SIZE;
|
||||
u32 i = map_size;
|
||||
|
||||
if (edges_only) {
|
||||
|
||||
while (i--) {
|
||||
|
||||
if (*mem) *mem = 1;
|
||||
if (*mem) { *mem = 1; }
|
||||
mem++;
|
||||
|
||||
}
|
||||
@ -151,10 +152,13 @@ static void classify_counts(afl_forkserver_t *fsrv) {
|
||||
static inline u8 anything_set(afl_forkserver_t *fsrv) {
|
||||
|
||||
u32 *ptr = (u32 *)fsrv->trace_bits;
|
||||
u32 i = (MAP_SIZE >> 2);
|
||||
u32 i = (map_size >> 2);
|
||||
|
||||
while (i--)
|
||||
if (*(ptr++)) return 1;
|
||||
while (i--) {
|
||||
|
||||
if (*(ptr++)) { return 1; }
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -173,13 +177,16 @@ static void read_initial_file(void) {
|
||||
struct stat st;
|
||||
s32 fd = open(in_file, O_RDONLY);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", in_file);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", in_file); }
|
||||
|
||||
if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file.");
|
||||
if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); }
|
||||
|
||||
if (st.st_size >= TMIN_MAX_FILE) {
|
||||
|
||||
if (st.st_size >= TMIN_MAX_FILE)
|
||||
FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
|
||||
|
||||
}
|
||||
|
||||
in_len = st.st_size;
|
||||
in_data = ck_alloc_nozero(in_len);
|
||||
|
||||
@ -201,7 +208,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
|
||||
|
||||
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
if (ret < 0) PFATAL("Unable to create '%s'", path);
|
||||
if (ret < 0) { PFATAL("Unable to create '%s'", path); }
|
||||
|
||||
ck_write(ret, mem, len, path);
|
||||
|
||||
@ -222,7 +229,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||
fsrv_run_result_t ret =
|
||||
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
|
||||
|
||||
if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child");
|
||||
if (ret == FSRV_RUN_ERROR) { FATAL("Couldn't run child"); }
|
||||
|
||||
if (stop_soon) {
|
||||
|
||||
@ -238,9 +245,14 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||
|
||||
switch (ret) {
|
||||
|
||||
case FSRV_RUN_TMOUT: return 1;
|
||||
case FSRV_RUN_CRASH: missed_crashes++; return 0;
|
||||
default: missed_hangs++; return 0;
|
||||
case FSRV_RUN_TMOUT:
|
||||
return 1;
|
||||
case FSRV_RUN_CRASH:
|
||||
missed_crashes++;
|
||||
return 0;
|
||||
default:
|
||||
missed_hangs++;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@ -260,11 +272,11 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||
|
||||
if (ret == FSRV_RUN_CRASH) {
|
||||
|
||||
if (first_run) crash_mode = 1;
|
||||
if (first_run) { crash_mode = 1; }
|
||||
|
||||
if (crash_mode) {
|
||||
|
||||
if (!exact_mode) return 1;
|
||||
if (!exact_mode) { return 1; }
|
||||
|
||||
} else {
|
||||
|
||||
@ -286,13 +298,13 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||
|
||||
}
|
||||
|
||||
if (ret == FSRV_RUN_NOINST) FATAL("Binary not instrumented?");
|
||||
if (ret == FSRV_RUN_NOINST) { FATAL("Binary not instrumented?"); }
|
||||
|
||||
u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST);
|
||||
|
||||
if (first_run) orig_cksum = cksum;
|
||||
if (first_run) { orig_cksum = cksum; }
|
||||
|
||||
if (orig_cksum == cksum) return 1;
|
||||
if (orig_cksum == cksum) { return 1; }
|
||||
|
||||
missed_paths++;
|
||||
return 0;
|
||||
@ -319,7 +331,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
|
||||
set_len = next_pow2(in_len / TMIN_SET_STEPS);
|
||||
set_pos = 0;
|
||||
|
||||
if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE;
|
||||
if (set_len < TMIN_SET_MIN_SIZE) { set_len = TMIN_SET_MIN_SIZE; }
|
||||
|
||||
ACTF(cBRI "Stage #0: " cRST "One-time block normalization...");
|
||||
|
||||
@ -327,8 +339,11 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
u32 use_len = MIN(set_len, in_len - set_pos);
|
||||
|
||||
for (i = 0; i < use_len; i++)
|
||||
if (in_data[set_pos + i] != '0') break;
|
||||
for (i = 0; i < use_len; i++) {
|
||||
|
||||
if (in_data[set_pos + i] != '0') { break; }
|
||||
|
||||
}
|
||||
|
||||
if (i != use_len) {
|
||||
|
||||
@ -373,7 +388,7 @@ next_pass:
|
||||
|
||||
next_del_blksize:
|
||||
|
||||
if (!del_len) del_len = 1;
|
||||
if (!del_len) { del_len = 1; }
|
||||
del_pos = 0;
|
||||
prev_del = 1;
|
||||
|
||||
@ -386,7 +401,7 @@ next_del_blksize:
|
||||
s32 tail_len;
|
||||
|
||||
tail_len = in_len - del_pos - del_len;
|
||||
if (tail_len < 0) tail_len = 0;
|
||||
if (tail_len < 0) { tail_len = 0; }
|
||||
|
||||
/* If we have processed at least one full block (initially, prev_del == 1),
|
||||
and we did so without deleting the previous one, and we aren't at the
|
||||
@ -419,12 +434,14 @@ next_del_blksize:
|
||||
|
||||
changed_any = 1;
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
del_pos += del_len;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (del_len > 1 && in_len >= 1) {
|
||||
|
||||
del_len /= 2;
|
||||
@ -434,11 +451,14 @@ next_del_blksize:
|
||||
|
||||
OKF("Block removal complete, %u bytes deleted.", stage_o_len - in_len);
|
||||
|
||||
if (!in_len && changed_any)
|
||||
if (!in_len && changed_any) {
|
||||
|
||||
WARNF(cLRD
|
||||
"Down to zero bytes - check the command line and mem limit!" cRST);
|
||||
|
||||
if (cur_pass > 1 && !changed_any) goto finalize_all;
|
||||
}
|
||||
|
||||
if (cur_pass > 1 && !changed_any) { goto finalize_all; }
|
||||
|
||||
/*************************
|
||||
* ALPHABET MINIMIZATION *
|
||||
@ -452,7 +472,7 @@ next_del_blksize:
|
||||
|
||||
for (i = 0; i < in_len; i++) {
|
||||
|
||||
if (!alpha_map[in_data[i]]) alpha_size++;
|
||||
if (!alpha_map[in_data[i]]) { alpha_size++; }
|
||||
alpha_map[in_data[i]]++;
|
||||
|
||||
}
|
||||
@ -465,12 +485,15 @@ next_del_blksize:
|
||||
u32 r;
|
||||
u8 res;
|
||||
|
||||
if (i == '0' || !alpha_map[i]) continue;
|
||||
if (i == '0' || !alpha_map[i]) { continue; }
|
||||
|
||||
memcpy(tmp_buf, in_data, in_len);
|
||||
|
||||
for (r = 0; r < in_len; r++)
|
||||
if (tmp_buf[r] == i) tmp_buf[r] = '0';
|
||||
for (r = 0; r < in_len; r++) {
|
||||
|
||||
if (tmp_buf[r] == i) { tmp_buf[r] = '0'; }
|
||||
|
||||
}
|
||||
|
||||
res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
|
||||
|
||||
@ -505,7 +528,7 @@ next_del_blksize:
|
||||
|
||||
u8 res, orig = tmp_buf[i];
|
||||
|
||||
if (orig == '0') continue;
|
||||
if (orig == '0') { continue; }
|
||||
tmp_buf[i] = '0';
|
||||
|
||||
res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
|
||||
@ -516,22 +539,24 @@ next_del_blksize:
|
||||
alpha_del2++;
|
||||
changed_any = 1;
|
||||
|
||||
} else
|
||||
} else {
|
||||
|
||||
tmp_buf[i] = orig;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
alpha_d_total += alpha_del2;
|
||||
|
||||
OKF("Character minimization done, %u byte%s replaced.", alpha_del2,
|
||||
alpha_del2 == 1 ? "" : "s");
|
||||
|
||||
if (changed_any) goto next_pass;
|
||||
if (changed_any) { goto next_pass; }
|
||||
|
||||
finalize_all:
|
||||
|
||||
if (tmp_buf) ck_free(tmp_buf);
|
||||
if (tmp_buf) { ck_free(tmp_buf); }
|
||||
|
||||
if (hang_mode) {
|
||||
|
||||
@ -557,9 +582,12 @@ finalize_all:
|
||||
missed_hangs ? cLRD : "", missed_hangs);
|
||||
|
||||
if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs &&
|
||||
!hang_mode)
|
||||
!hang_mode) {
|
||||
|
||||
WARNF(cLRD "Frequent timeouts - results may be skewed." cRST);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Handle Ctrl-C and the like. */
|
||||
@ -578,7 +606,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
u8 *x;
|
||||
|
||||
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
||||
if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null");
|
||||
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||
|
||||
if (!out_file) {
|
||||
|
||||
@ -587,7 +615,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
if (access(use_dir, R_OK | W_OK | X_OK)) {
|
||||
|
||||
use_dir = get_afl_env("TMPDIR");
|
||||
if (!use_dir) use_dir = "/tmp";
|
||||
if (!use_dir) { use_dir = "/tmp"; }
|
||||
|
||||
}
|
||||
|
||||
@ -599,7 +627,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
|
||||
fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file);
|
||||
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
|
||||
|
||||
/* Set sane defaults... */
|
||||
|
||||
@ -607,27 +635,39 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
|
||||
if (x) {
|
||||
|
||||
if (!strstr(x, "abort_on_error=1"))
|
||||
if (!strstr(x, "abort_on_error=1")) {
|
||||
|
||||
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
|
||||
|
||||
if (!strstr(x, "symbolize=0"))
|
||||
}
|
||||
|
||||
if (!strstr(x, "symbolize=0")) {
|
||||
|
||||
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
x = get_afl_env("MSAN_OPTIONS");
|
||||
|
||||
if (x) {
|
||||
|
||||
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR)))
|
||||
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
|
||||
|
||||
FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
|
||||
MSAN_ERROR) " - please fix!");
|
||||
|
||||
if (!strstr(x, "symbolize=0"))
|
||||
}
|
||||
|
||||
if (!strstr(x, "symbolize=0")) {
|
||||
|
||||
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setenv("ASAN_OPTIONS",
|
||||
"abort_on_error=1:"
|
||||
"detect_leaks=0:"
|
||||
@ -652,20 +692,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
if (afl_preload[i] == ',') {
|
||||
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
}
|
||||
|
||||
if (qemu_preload) {
|
||||
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
qemu_preload, afl_preload, afl_preload);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
|
||||
afl_preload, afl_preload);
|
||||
|
||||
}
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
@ -740,6 +788,8 @@ static void usage(u8 *argv0) {
|
||||
" (must contain abort_on_error=1 and symbolize=0)\n"
|
||||
"MSAN_OPTIONS: custom settings for MSAN\n"
|
||||
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\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_TMIN_EXACT: require execution paths to match for crashing inputs\n"
|
||||
|
||||
@ -762,45 +812,51 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
afl_forkserver_t fsrv_var = {0};
|
||||
afl_forkserver_t *fsrv = &fsrv_var;
|
||||
afl_fsrv_init(fsrv);
|
||||
map_size = get_map_size();
|
||||
fsrv->map_size = map_size;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
||||
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
|
||||
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0)
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'i':
|
||||
|
||||
if (in_file) FATAL("Multiple -i options not supported");
|
||||
if (in_file) { FATAL("Multiple -i options not supported"); }
|
||||
in_file = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
|
||||
if (output_file) FATAL("Multiple -o options not supported");
|
||||
if (output_file) { FATAL("Multiple -o options not supported"); }
|
||||
output_file = optarg;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
if (out_file) FATAL("Multiple -f options not supported");
|
||||
if (out_file) { FATAL("Multiple -f options not supported"); }
|
||||
fsrv->use_stdin = 0;
|
||||
out_file = optarg;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
|
||||
if (edges_only) FATAL("Multiple -e options not supported");
|
||||
if (hang_mode)
|
||||
if (edges_only) { FATAL("Multiple -e options not supported"); }
|
||||
if (hang_mode) {
|
||||
|
||||
FATAL("Edges only and hang mode are mutually exclusive.");
|
||||
|
||||
}
|
||||
|
||||
edges_only = 1;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
|
||||
if (exit_crash) FATAL("Multiple -x options not supported");
|
||||
if (exit_crash) { FATAL("Multiple -x options not supported"); }
|
||||
exit_crash = 1;
|
||||
break;
|
||||
|
||||
@ -808,10 +864,10 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
u8 suffix = 'M';
|
||||
|
||||
if (mem_limit_given) FATAL("Multiple -m options not supported");
|
||||
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
|
||||
mem_limit_given = 1;
|
||||
|
||||
if (!optarg) FATAL("Wrong usage of -m");
|
||||
if (!optarg) { FATAL("Wrong usage of -m"); }
|
||||
|
||||
if (!strcmp(optarg, "none")) {
|
||||
|
||||
@ -821,66 +877,83 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
|
||||
optarg[0] == '-')
|
||||
optarg[0] == '-') {
|
||||
|
||||
FATAL("Bad syntax used for -m");
|
||||
|
||||
switch (suffix) {
|
||||
|
||||
case 'T': fsrv->mem_limit *= 1024 * 1024; break;
|
||||
case 'G': fsrv->mem_limit *= 1024; break;
|
||||
case 'k': fsrv->mem_limit /= 1024; break;
|
||||
case 'M': break;
|
||||
|
||||
default: FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m");
|
||||
switch (suffix) {
|
||||
|
||||
case 'T':
|
||||
fsrv->mem_limit *= 1024 * 1024;
|
||||
break;
|
||||
case 'G':
|
||||
fsrv->mem_limit *= 1024;
|
||||
break;
|
||||
case 'k':
|
||||
fsrv->mem_limit /= 1024;
|
||||
break;
|
||||
case 'M':
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL("Unsupported suffix or bad syntax for -m");
|
||||
|
||||
}
|
||||
|
||||
if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
|
||||
|
||||
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
|
||||
|
||||
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000)
|
||||
FATAL("Value of -m out of range on 32-bit systems");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
if (timeout_given) FATAL("Multiple -t options not supported");
|
||||
if (timeout_given) { FATAL("Multiple -t options not supported"); }
|
||||
timeout_given = 1;
|
||||
|
||||
if (!optarg) FATAL("Wrong usage of -t");
|
||||
if (!optarg) { FATAL("Wrong usage of -t"); }
|
||||
|
||||
fsrv->exec_tmout = atoi(optarg);
|
||||
|
||||
if (fsrv->exec_tmout < 10 || optarg[0] == '-')
|
||||
if (fsrv->exec_tmout < 10 || optarg[0] == '-') {
|
||||
|
||||
FATAL("Dangerously low value of -t");
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
|
||||
if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported");
|
||||
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU;
|
||||
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
|
||||
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
|
||||
|
||||
fsrv->qemu_mode = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
|
||||
if (unicorn_mode) FATAL("Multiple -Q options not supported");
|
||||
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN;
|
||||
if (unicorn_mode) { FATAL("Multiple -Q options not supported"); }
|
||||
if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
|
||||
|
||||
unicorn_mode = 1;
|
||||
break;
|
||||
|
||||
case 'W': /* Wine+QEMU mode */
|
||||
|
||||
if (use_wine) FATAL("Multiple -W options not supported");
|
||||
if (use_wine) { FATAL("Multiple -W options not supported"); }
|
||||
fsrv->qemu_mode = 1;
|
||||
use_wine = 1;
|
||||
|
||||
if (!mem_limit_given) fsrv->mem_limit = 0;
|
||||
if (!mem_limit_given) { fsrv->mem_limit = 0; }
|
||||
|
||||
break;
|
||||
|
||||
@ -888,9 +961,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
/* Minimizes a testcase to the minimum that still times out */
|
||||
|
||||
if (hang_mode) FATAL("Multipe -H options not supported");
|
||||
if (edges_only)
|
||||
if (hang_mode) { FATAL("Multipe -H options not supported"); }
|
||||
if (edges_only) {
|
||||
|
||||
FATAL("Edges only and hang mode are mutually exclusive.");
|
||||
|
||||
}
|
||||
|
||||
hang_mode = 1;
|
||||
break;
|
||||
|
||||
@ -909,9 +986,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
The option may be extended and made more official if it proves
|
||||
to be useful. */
|
||||
|
||||
if (mask_bitmap) FATAL("Multiple -B options not supported");
|
||||
mask_bitmap = ck_alloc(MAP_SIZE);
|
||||
read_bitmap(optarg, mask_bitmap, MAP_SIZE);
|
||||
if (mask_bitmap) { FATAL("Multiple -B options not supported"); }
|
||||
mask_bitmap = ck_alloc(map_size);
|
||||
read_bitmap(optarg, mask_bitmap, map_size);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@ -919,16 +996,19 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
return -1;
|
||||
break;
|
||||
|
||||
default: usage(argv[0]);
|
||||
default:
|
||||
usage(argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc || !in_file || !output_file) usage(argv[0]);
|
||||
}
|
||||
|
||||
if (optind == argc || !in_file || !output_file) { usage(argv[0]); }
|
||||
|
||||
check_environment_vars(envp);
|
||||
|
||||
sharedmem_t shm = {0};
|
||||
fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0);
|
||||
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||
|
||||
atexit(at_exit_handler);
|
||||
setup_signal_handlers();
|
||||
@ -940,17 +1020,24 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (fsrv->qemu_mode) {
|
||||
|
||||
if (use_wine)
|
||||
if (use_wine) {
|
||||
|
||||
use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind,
|
||||
argv + optind);
|
||||
else
|
||||
|
||||
} else {
|
||||
|
||||
use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind,
|
||||
argv + optind);
|
||||
|
||||
} else
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
use_argv = argv + optind;
|
||||
|
||||
}
|
||||
|
||||
exact_mode = !!get_afl_env("AFL_TMIN_EXACT");
|
||||
|
||||
if (hang_mode && exact_mode) {
|
||||
@ -972,17 +1059,23 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
tmin_run_target(fsrv, use_argv, in_data, in_len, 1);
|
||||
|
||||
if (hang_mode && !fsrv->last_run_timed_out)
|
||||
if (hang_mode && !fsrv->last_run_timed_out) {
|
||||
|
||||
FATAL(
|
||||
"Target binary did not time out but hang minimization mode "
|
||||
"(-H) was set (-t %u).",
|
||||
fsrv->exec_tmout);
|
||||
|
||||
if (fsrv->last_run_timed_out && !hang_mode)
|
||||
}
|
||||
|
||||
if (fsrv->last_run_timed_out && !hang_mode) {
|
||||
|
||||
FATAL(
|
||||
"Target binary times out (adjusting -t may help). Use -H to minimize a "
|
||||
"hang.");
|
||||
|
||||
}
|
||||
|
||||
if (hang_mode) {
|
||||
|
||||
OKF("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode.");
|
||||
@ -992,7 +1085,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
OKF("Program terminates normally, minimizing in " cCYA "instrumented" cRST
|
||||
" mode.");
|
||||
|
||||
if (!anything_set(fsrv)) FATAL("No instrumentation detected.");
|
||||
if (!anything_set(fsrv)) { FATAL("No instrumentation detected."); }
|
||||
|
||||
} else {
|
||||
|
||||
@ -1007,7 +1100,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
ACTF("Writing output to '%s'...", output_file);
|
||||
|
||||
unlink(out_file);
|
||||
if (out_file) ck_free(out_file);
|
||||
if (out_file) { ck_free(out_file); }
|
||||
out_file = NULL;
|
||||
|
||||
close(write_to_file(output_file, in_data, in_len));
|
||||
@ -1016,9 +1109,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
afl_shm_deinit(&shm);
|
||||
afl_fsrv_deinit(fsrv);
|
||||
if (fsrv->target_path) ck_free(fsrv->target_path);
|
||||
if (mask_bitmap) ck_free(mask_bitmap);
|
||||
if (in_data) ck_free(in_data);
|
||||
if (fsrv->target_path) { ck_free(fsrv->target_path); }
|
||||
if (mask_bitmap) { ck_free(mask_bitmap); }
|
||||
if (in_data) { ck_free(in_data); }
|
||||
|
||||
argv_cpy_free(argv);
|
||||
|
||||
|
32
test/test.sh
32
test/test.sh
@ -81,6 +81,8 @@ test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
|
||||
} || {
|
||||
AFL_GCC=afl-gcc
|
||||
}
|
||||
command -v gcc || AFL_GCC=afl-clang
|
||||
|
||||
SYS=`uname -m`
|
||||
|
||||
GREY="\\033[1;90m"
|
||||
@ -666,8 +668,8 @@ test -z "$AFL_CC" && {
|
||||
|
||||
$ECHO "$BLUE[*] Testing: qemu_mode"
|
||||
test -e ../afl-qemu-trace && {
|
||||
gcc -pie -fPIE -o test-instr ../test-instr.c
|
||||
gcc -o test-compcov test-compcov.c
|
||||
cc -pie -fPIE -o test-instr ../test-instr.c
|
||||
cc -o test-compcov test-compcov.c
|
||||
test -e test-instr -a -e test-compcov && {
|
||||
{
|
||||
mkdir -p in
|
||||
@ -691,7 +693,14 @@ test -e ../afl-qemu-trace && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds"
|
||||
{
|
||||
{
|
||||
export AFL_ENTRYPOINT=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )`
|
||||
if file test-instr | grep -q "32-bit"; then
|
||||
# for 32-bit reduce 8 nibbles to the lower 7 nibbles
|
||||
ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
|
||||
else
|
||||
# for 64-bit reduce 16 nibbles to the lower 9 nibbles
|
||||
ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
|
||||
fi
|
||||
export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}`
|
||||
$ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr)
|
||||
../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr
|
||||
unset AFL_ENTRYPOINT
|
||||
@ -759,7 +768,14 @@ test -e ../afl-qemu-trace && {
|
||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
|
||||
{
|
||||
export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )`
|
||||
if file test-instr | grep -q "32-bit"; then
|
||||
# for 32-bit reduce 8 nibbles to the lower 7 nibbles
|
||||
ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
|
||||
else
|
||||
# for 64-bit reduce 16 nibbles to the lower 9 nibbles
|
||||
ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
|
||||
fi
|
||||
export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4${ADDR_LOWER_PART}`
|
||||
export AFL_QEMU_PERSISTENT_GPR=1
|
||||
$ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')"
|
||||
env|grep AFL_|sort
|
||||
@ -935,7 +951,15 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && {
|
||||
test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
|
||||
unset AFL_CC
|
||||
# Compile the vulnerable program
|
||||
test -e ../afl-clang-fast && {
|
||||
../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
} || {
|
||||
test -e ../afl-gcc-fast && {
|
||||
../afl-gcc-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
} || {
|
||||
../afl-gcc -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
}
|
||||
}
|
||||
# Compile the custom mutator
|
||||
make -C ../examples/custom_mutators libexamplemutator.so > /dev/null 2>&1
|
||||
test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && {
|
||||
|
1
unicorn_mode/UNICORNAFL_VERSION
Normal file
1
unicorn_mode/UNICORNAFL_VERSION
Normal file
@ -0,0 +1 @@
|
||||
25ae270
|
31
unicorn_mode/build_unicorn_support.sh
Normal file → Executable file
31
unicorn_mode/build_unicorn_support.sh
Normal file → Executable file
@ -33,6 +33,8 @@
|
||||
# You must make sure that Unicorn Engine is not already installed before
|
||||
# running this script. If it is, please uninstall it first.
|
||||
|
||||
UNICORNAFL_VERSION="$(cat ./UNICORNAFL_VERSION)"
|
||||
|
||||
echo "================================================="
|
||||
echo "UnicornAFL build script"
|
||||
echo "================================================="
|
||||
@ -105,7 +107,7 @@ for i in $PYTHONBIN automake autoconf git $MAKECMD $TARCMD; do
|
||||
|
||||
done
|
||||
|
||||
if ! type $EASY_INSTALL > /dev/null; then
|
||||
if ! command -v $EASY_INSTALL >/dev/null; then
|
||||
|
||||
# work around for installs with executable easy_install
|
||||
EASY_INSTALL_FOUND=0
|
||||
@ -121,7 +123,7 @@ if ! type $EASY_INSTALL > /dev/null; then
|
||||
|
||||
fi
|
||||
done
|
||||
if [ '!' $EASY_INSTALL_FOUND ]; then
|
||||
if [ "0" = $EASY_INSTALL_FOUND ]; then
|
||||
|
||||
echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'."
|
||||
PREREQ_NOTFOUND=1
|
||||
@ -144,26 +146,37 @@ fi
|
||||
echo "[+] All checks passed!"
|
||||
|
||||
echo "[*] Making sure unicornafl is checked out"
|
||||
rm -rf unicornafl # workaround for travis ... sadly ...
|
||||
#test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } }
|
||||
test -d unicornafl || {
|
||||
|
||||
git status 1>/dev/null 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "[*] initializing unicornafl submodule"
|
||||
git submodule init || exit 1
|
||||
git submodule update 2>/dev/null # ignore errors
|
||||
else
|
||||
echo "[*] cloning unicornafl"
|
||||
test -d unicornafl || {
|
||||
CNT=1
|
||||
while [ '!' -d unicornafl -a "$CNT" -lt 4 ]; do
|
||||
echo "Trying to clone unicornafl (attempt $CNT/3)"
|
||||
git clone https://github.com/AFLplusplus/unicornafl
|
||||
CNT=`expr "$CNT" + 1`
|
||||
done
|
||||
}
|
||||
}
|
||||
fi
|
||||
|
||||
test -d unicornafl || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
|
||||
echo "[+] Got unicornafl."
|
||||
|
||||
cd "unicornafl" || exit 1
|
||||
echo "[*] Checking out $UNICORNAFL_VERSION"
|
||||
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
|
||||
git checkout "$UNICORNAFL_VERSION" || exit 1
|
||||
|
||||
echo "[*] making sure config.h matches"
|
||||
cp "../config.h" "./unicornafl/" || exit 1
|
||||
cp "../../config.h" "." || exit 1
|
||||
|
||||
echo "[*] Configuring Unicorn build..."
|
||||
|
||||
cd "unicornafl" || exit 1
|
||||
|
||||
echo "[+] Configuration complete."
|
||||
|
||||
echo "[*] Attempting to build unicornafl (fingers crossed!)..."
|
||||
|
1
unicorn_mode/unicornafl
Submodule
1
unicorn_mode/unicornafl
Submodule
Submodule unicorn_mode/unicornafl added at 25ae270c1b
25
unicorn_mode/update_uc_ref.sh
Executable file
25
unicorn_mode/update_uc_ref.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#/bin/sh
|
||||
|
||||
UC_VERSION_FILE='./UNICORNAFL_VERSION'
|
||||
|
||||
NEW_VERSION="$1"
|
||||
if [ -z "$NEW_VERSION" ]; then
|
||||
echo "Internal script to update bound unicornafl version."
|
||||
echo
|
||||
echo "Usage: ./update_uc_ref.sh <new commit hash>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git submodule init && git submodule update || exit 1
|
||||
cd ./unicornafl
|
||||
git fetch origin master 1>/dev/null || exit 1
|
||||
git stash 1>/dev/null 2>/dev/null
|
||||
git stash drop 1>/dev/null 2>/dev/null
|
||||
git checkout "$NEW_VERSION" || exit 1
|
||||
|
||||
cd ..
|
||||
|
||||
rm "$UC_VERSION_FILE"
|
||||
echo "$NEW_VERSION" > "$UC_VERSION_FILE"
|
||||
|
||||
echo "Done. New unicornafl version is $NEW_VERSION."
|
Reference in New Issue
Block a user