Merge branch 'dev' of github.com:vanhauser-thc/AFLplusplus into dev

This commit is contained in:
Andrea Fioraldi
2020-04-22 13:51:40 +02:00
65 changed files with 3469 additions and 1534 deletions

View File

@ -10,7 +10,7 @@ AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false

View File

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

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

@ -0,0 +1,3 @@
[submodule "unicorn_mode/unicornafl"]
path = unicorn_mode/unicornafl
url = https://github.com/AFLplusplus/unicornafl.git

View File

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

View File

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

View File

@ -4,9 +4,9 @@
![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=master)
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)

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,8 @@ int target_func(unsigned char *buf, int size) {
}
break;
default: break;
default:
break;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,7 +752,7 @@ 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:"
" 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"
@ -758,10 +763,10 @@ int main(int argc, char **argv, char **envp) {
#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());

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,9 @@ int target_func(char *buf, int size) {
}
break;
default: puts("default action"); break;
default:
puts("default action");
break;
}

View File

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

View File

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

View File

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

View File

@ -51,9 +51,11 @@ int main() {
switch (z) {
case 0xBEEF: break;
case 0xBEEF:
break;
default: return 4;
default:
return 4;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,13 +332,19 @@ 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
void classify_counts(afl_forkserver_t *fsrv) {
@ -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);

View File

@ -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. */

View File

@ -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,37 +540,51 @@ 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. */
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

View File

@ -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,35 +197,50 @@ 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) {
u8 needs_write = 0, fault = 0;
@ -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

View File

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

View File

@ -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);
@ -261,6 +281,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
goes over afl->top_rated[] entries, and then sequentially grabs winners for
previously-unseen bytes (temp_v) and marks them as favored, at least
@ -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;
}

View File

@ -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,11 +101,14 @@ 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) {
struct range *ranges = add_range(NULL, 0, len);
@ -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; }
}

View File

@ -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,29 +111,36 @@ 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
to warn about flaky or otherwise problematic test cases early on; and when
new paths are discovered to detect variable behavior and so on. */
@ -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;
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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,23 +375,34 @@ 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));
@ -381,6 +410,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
}
}
/* Handle Ctrl-C and the like. */
static void handle_stop_sig(int sig) {
@ -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);

View File

@ -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,11 +582,14 @@ 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. */
static void handle_stop_sig(int sig) {
@ -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);

View File

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

View File

@ -0,0 +1 @@
25ae270

27
unicorn_mode/build_unicorn_support.sh Normal file → Executable file
View 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,8 +146,14 @@ 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 .. ; } }
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
@ -154,16 +162,21 @@ test -d 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!)..."

25
unicorn_mode/update_uc_ref.sh Executable file
View 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."