mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 19:08:08 +00:00
Merge branch '420' into dev
This commit is contained in:
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -5,6 +5,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- stable
|
- stable
|
||||||
- dev
|
- dev
|
||||||
|
- 420
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- dev # No need for stable-pull-request, as that equals dev-push
|
- dev # No need for stable-pull-request, as that equals dev-push
|
||||||
|
@ -471,8 +471,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
|||||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||||
|
|
||||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||||
|
|
||||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||||
|
|
||||||
GitHub version: 4.10c
|
GitHub version: 4.20a
|
||||||
|
|
||||||
Repository:
|
Repository:
|
||||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
This is the list of all noteworthy changes made in every public
|
This is the list of all noteworthy changes made in every public
|
||||||
release of the tool. See README.md for the general instruction manual.
|
release of the tool. See README.md for the general instruction manual.
|
||||||
|
|
||||||
|
### Version ++4.20a (dev)
|
||||||
|
- afl-fuzz:
|
||||||
|
- the new deterministic fuzzing feature is now activated by default,
|
||||||
|
deactivate with -z. Parameters -d and -D are ignored.
|
||||||
|
- afl-cc:
|
||||||
|
- added collision free caller instrumentation to LTO mode. activate with
|
||||||
|
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
|
||||||
|
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
|
||||||
|
|
||||||
|
|
||||||
### Version ++4.10c (release)
|
### Version ++4.10c (release)
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
- default power schedule is now EXPLORE, due a fix in fast schedules
|
- default power schedule is now EXPLORE, due a fix in fast schedules
|
||||||
|
@ -248,6 +248,9 @@ use (which only ever the author of this LTO implementation will use). These are
|
|||||||
used if several separated instrumentations are performed which are then later
|
used if several separated instrumentations are performed which are then later
|
||||||
combined.
|
combined.
|
||||||
|
|
||||||
|
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
|
||||||
|
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
|
||||||
|
to dig deeper into a real function. Default 0.
|
||||||
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
||||||
to which function. This helps to identify functions with variable bytes or
|
to which function. This helps to identify functions with variable bytes or
|
||||||
which functions were touched by an input.
|
which functions were touched by an input.
|
||||||
|
@ -38,18 +38,16 @@
|
|||||||
|
|
||||||
#define SHAPE_BYTES(x) (x + 1)
|
#define SHAPE_BYTES(x) (x + 1)
|
||||||
|
|
||||||
#define CMP_TYPE_INS 1
|
#define CMP_TYPE_INS 0
|
||||||
#define CMP_TYPE_RTN 2
|
#define CMP_TYPE_RTN 1
|
||||||
|
|
||||||
struct cmp_header {
|
struct cmp_header {
|
||||||
|
|
||||||
unsigned hits : 24;
|
unsigned hits : 6; // up to 63 entries, we have CMP_MAP_H = 32
|
||||||
unsigned id : 24;
|
unsigned shape : 5; // 31+1 bytes
|
||||||
unsigned shape : 5;
|
unsigned type : 1; // 4, we use 3: none, rtn, cmp
|
||||||
unsigned type : 2;
|
unsigned attribute : 4; // 16 for arithmetic comparison types
|
||||||
unsigned attribute : 4;
|
//unsigned reserved : 6;
|
||||||
unsigned overflow : 1;
|
|
||||||
unsigned reserved : 4;
|
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
@ -59,14 +57,17 @@ struct cmp_operands {
|
|||||||
u64 v1;
|
u64 v1;
|
||||||
u64 v0_128;
|
u64 v0_128;
|
||||||
u64 v1_128;
|
u64 v1_128;
|
||||||
|
u64 unused;
|
||||||
|
u8 unused1;
|
||||||
|
u8 unused2;
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct cmpfn_operands {
|
struct cmpfn_operands {
|
||||||
|
|
||||||
u8 v0[31];
|
u8 v0[32];
|
||||||
u8 v0_len;
|
u8 v0_len;
|
||||||
u8 v1[31];
|
u8 v1[32];
|
||||||
u8 v1_len;
|
u8 v1_len;
|
||||||
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
@ -21,7 +21,7 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
||||||
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
||||||
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
||||||
"AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
||||||
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
||||||
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
||||||
|
@ -49,6 +49,14 @@ typedef uint128_t u128;
|
|||||||
#define FS_ERROR_OLD_CMPLOG 32
|
#define FS_ERROR_OLD_CMPLOG 32
|
||||||
#define FS_ERROR_OLD_CMPLOG_QEMU 64
|
#define FS_ERROR_OLD_CMPLOG_QEMU 64
|
||||||
|
|
||||||
|
/* New Forkserver */
|
||||||
|
#define FS_NEW_VERSION_MIN 1
|
||||||
|
#define FS_NEW_VERSION_MAX 1
|
||||||
|
#define FS_NEW_ERROR 0xeffe0000
|
||||||
|
#define FS_NEW_OPT_MAPSIZE 0x00000001 // parameter: 32 bit value
|
||||||
|
#define FS_NEW_OPT_SHDMEM_FUZZ 0x00000002 // parameter: none
|
||||||
|
#define FS_NEW_OPT_AUTODICT 0x00000800 // autodictionary data
|
||||||
|
|
||||||
/* Reporting options */
|
/* Reporting options */
|
||||||
#define FS_OPT_ENABLED 0x80000001
|
#define FS_OPT_ENABLED 0x80000001
|
||||||
#define FS_OPT_MAPSIZE 0x40000000
|
#define FS_OPT_MAPSIZE 0x40000000
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -190,6 +190,8 @@ __thread u32 __afl_prev_ctx;
|
|||||||
struct cmp_map *__afl_cmp_map;
|
struct cmp_map *__afl_cmp_map;
|
||||||
struct cmp_map *__afl_cmp_map_backup;
|
struct cmp_map *__afl_cmp_map_backup;
|
||||||
|
|
||||||
|
static u8 __afl_cmplog_max_len = 32; // 16-32
|
||||||
|
|
||||||
/* Child pid? */
|
/* Child pid? */
|
||||||
|
|
||||||
static s32 child_pid;
|
static s32 child_pid;
|
||||||
@ -268,7 +270,7 @@ static void send_forkserver_error(int error) {
|
|||||||
|
|
||||||
u32 status;
|
u32 status;
|
||||||
if (!error || error > 0xffff) return;
|
if (!error || error > 0xffff) return;
|
||||||
status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
|
status = (FS_NEW_ERROR | error);
|
||||||
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
|
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -371,32 +373,13 @@ static void __afl_map_shm(void) {
|
|||||||
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
|
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
|
||||||
if (val < __afl_final_loc) {
|
if (val < __afl_final_loc) {
|
||||||
|
|
||||||
if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
|
if (__afl_final_loc > MAP_INITIAL_SIZE && !getenv("AFL_QUIET")) {
|
||||||
|
|
||||||
if (!getenv("AFL_QUIET"))
|
fprintf(stderr,
|
||||||
fprintf(stderr,
|
"Warning: AFL++ tools might need to set AFL_MAP_SIZE to %u "
|
||||||
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
|
"to be able to run this instrumented program if this "
|
||||||
"to be able to run this instrumented program!\n",
|
"crashes!\n",
|
||||||
__afl_final_loc);
|
__afl_final_loc);
|
||||||
|
|
||||||
if (id_str) {
|
|
||||||
|
|
||||||
send_forkserver_error(FS_ERROR_MAP_SIZE);
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (__afl_final_loc > MAP_INITIAL_SIZE && !getenv("AFL_QUIET")) {
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"Warning: AFL++ tools might need to set AFL_MAP_SIZE to %u "
|
|
||||||
"to be able to run this instrumented program if this "
|
|
||||||
"crashes!\n",
|
|
||||||
__afl_final_loc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,15 +387,6 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (getenv("AFL_DUMP_MAP_SIZE")) {
|
|
||||||
|
|
||||||
printf("%u\n", MAP_SIZE);
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing && (!id_str || !getenv(SHM_FUZZ_ENV_VAR) ||
|
if (__afl_sharedmem_fuzzing && (!id_str || !getenv(SHM_FUZZ_ENV_VAR) ||
|
||||||
@ -478,14 +452,13 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
if (__afl_debug) {
|
if (__afl_debug) {
|
||||||
|
|
||||||
fprintf(
|
fprintf(stderr,
|
||||||
stderr,
|
"DEBUG: (1) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
||||||
"DEBUG: (1) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE %u, "
|
||||||
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE %u, "
|
"__afl_final_loc %u, __afl_map_size %u\n",
|
||||||
"__afl_final_loc %u, __afl_map_size %u, max_size_forkserver %u/0x%x\n",
|
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
||||||
id_str == NULL ? "<null>" : id_str, __afl_area_ptr, __afl_area_initial,
|
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
||||||
__afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc,
|
__afl_final_loc, __afl_map_size);
|
||||||
__afl_map_size, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,12 +616,10 @@ static void __afl_map_shm(void) {
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
|
||||||
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
|
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
|
||||||
"%u, __afl_final_loc %u, __afl_map_size %u, "
|
"%u, __afl_final_loc %u, __afl_map_size %u",
|
||||||
"max_size_forkserver %u/0x%x\n",
|
|
||||||
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
|
||||||
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
|
||||||
__afl_final_loc, __afl_map_size, FS_OPT_MAX_MAPSIZE,
|
__afl_final_loc, __afl_map_size);
|
||||||
FS_OPT_MAX_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,6 +736,19 @@ static void __afl_map_shm(void) {
|
|||||||
|
|
||||||
#endif // __AFL_CODE_COVERAGE
|
#endif // __AFL_CODE_COVERAGE
|
||||||
|
|
||||||
|
if (!__afl_cmp_map && getenv("AFL_CMPLOG_DEBUG")) {
|
||||||
|
|
||||||
|
__afl_cmp_map_backup = __afl_cmp_map = malloc(sizeof(struct cmp_map));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv("AFL_CMPLOG_MAX_LEN")) {
|
||||||
|
|
||||||
|
int tmp = atoi(getenv("AFL_CMPLOG_MAX_LEN"));
|
||||||
|
if (tmp >= 16 && tmp <= 32) { __afl_cmplog_max_len = tmp; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unmap SHM. */
|
/* unmap SHM. */
|
||||||
@ -859,242 +843,6 @@ void write_error_with_location(char *text, char *filename, int linenumber) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
static void __afl_start_snapshots(void) {
|
|
||||||
|
|
||||||
static u8 tmp[4] = {0, 0, 0, 0};
|
|
||||||
u32 status = 0;
|
|
||||||
u32 already_read_first = 0;
|
|
||||||
u32 was_killed;
|
|
||||||
|
|
||||||
u8 child_stopped = 0;
|
|
||||||
|
|
||||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT | FS_OPT_NEWCMPLOG);
|
|
||||||
if (__afl_sharedmem_fuzzing) { status |= FS_OPT_SHDMEM_FUZZ; }
|
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
|
|
||||||
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
|
||||||
if (__afl_dictionary_len && __afl_dictionary) { status |= FS_OPT_AUTODICT; }
|
|
||||||
memcpy(tmp, &status, 4);
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
|
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("read to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_debug) {
|
|
||||||
|
|
||||||
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
|
|
||||||
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
|
||||||
|
|
||||||
__afl_map_shm_fuzz();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
|
|
||||||
__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
// great lets pass the dictionary through the forkserver FD
|
|
||||||
u32 len = __afl_dictionary_len, offset = 0;
|
|
||||||
s32 ret;
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary len\n",
|
|
||||||
strlen("Error: could not send dictionary len\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len != 0) {
|
|
||||||
|
|
||||||
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
|
||||||
|
|
||||||
if (ret < 1) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary\n",
|
|
||||||
strlen("Error: could not send dictionary\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= ret;
|
|
||||||
offset += ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// uh this forkserver does not understand extended option passing
|
|
||||||
// or does not want the dictionary
|
|
||||||
if (!__afl_fuzz_ptr) already_read_first = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (already_read_first) {
|
|
||||||
|
|
||||||
already_read_first = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Wait for parent by reading from the pipe. Abort if read fails. */
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("reading from afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _AFL_DOCUMENT_MUTATIONS
|
|
||||||
if (__afl_fuzz_ptr) {
|
|
||||||
|
|
||||||
static uint32_t counter = 0;
|
|
||||||
char fn[32];
|
|
||||||
sprintf(fn, "%09u:forkserver", counter);
|
|
||||||
s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
|
|
||||||
if (fd_doc >= 0) {
|
|
||||||
|
|
||||||
if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) {
|
|
||||||
|
|
||||||
fprintf(stderr, "write of mutation file failed: %s\n", fn);
|
|
||||||
unlink(fn);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd_doc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we stopped the child in persistent mode, but there was a race
|
|
||||||
condition and afl-fuzz already issued SIGKILL, write off the old
|
|
||||||
process. */
|
|
||||||
|
|
||||||
if (child_stopped && was_killed) {
|
|
||||||
|
|
||||||
child_stopped = 0;
|
|
||||||
if (waitpid(child_pid, &status, 0) < 0) {
|
|
||||||
|
|
||||||
write_error("child_stopped && was_killed");
|
|
||||||
_exit(1); // TODO why exit?
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!child_stopped) {
|
|
||||||
|
|
||||||
/* Once woken up, create a clone of our process. */
|
|
||||||
|
|
||||||
child_pid = fork();
|
|
||||||
if (child_pid < 0) {
|
|
||||||
|
|
||||||
write_error("fork");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In child process: close fds, resume execution. */
|
|
||||||
|
|
||||||
if (!child_pid) {
|
|
||||||
|
|
||||||
//(void)nice(-20); // does not seem to improve
|
|
||||||
|
|
||||||
signal(SIGCHLD, old_sigchld_handler);
|
|
||||||
signal(SIGTERM, old_sigterm_handler);
|
|
||||||
|
|
||||||
close(FORKSRV_FD);
|
|
||||||
close(FORKSRV_FD + 1);
|
|
||||||
|
|
||||||
if (!afl_snapshot_take(AFL_SNAPSHOT_MMAP | AFL_SNAPSHOT_FDS |
|
|
||||||
AFL_SNAPSHOT_REGS | AFL_SNAPSHOT_EXIT)) {
|
|
||||||
|
|
||||||
raise(SIGSTOP);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__afl_area_ptr[0] = 1;
|
|
||||||
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Special handling for persistent mode: if the child is alive but
|
|
||||||
currently stopped, simply restart it with SIGCONT. */
|
|
||||||
|
|
||||||
kill(child_pid, SIGCONT);
|
|
||||||
child_stopped = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In parent process: write PID to pipe, then wait for child. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("write to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitpid(child_pid, &status, WUNTRACED) < 0) {
|
|
||||||
|
|
||||||
write_error("waitpid");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In persistent mode, the child stops itself with SIGSTOP to indicate
|
|
||||||
a successful run. In this case, we want to wake it up without forking
|
|
||||||
again. */
|
|
||||||
|
|
||||||
if (WIFSTOPPED(status)) child_stopped = 1;
|
|
||||||
|
|
||||||
/* Relay wait status to pipe, then loop back. */
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) {
|
|
||||||
|
|
||||||
write_error("writing to afl-fuzz");
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fork server logic. */
|
/* Fork server logic. */
|
||||||
|
|
||||||
static void __afl_start_forkserver(void) {
|
static void __afl_start_forkserver(void) {
|
||||||
@ -1107,114 +855,93 @@ static void __afl_start_forkserver(void) {
|
|||||||
old_sigterm_handler = orig_action.sa_handler;
|
old_sigterm_handler = orig_action.sa_handler;
|
||||||
signal(SIGTERM, at_exit);
|
signal(SIGTERM, at_exit);
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
|
|
||||||
afl_snapshot_init() >= 0) {
|
|
||||||
|
|
||||||
__afl_start_snapshots();
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u8 tmp[4] = {0, 0, 0, 0};
|
|
||||||
u32 status_for_fsrv = 0;
|
|
||||||
u32 already_read_first = 0;
|
u32 already_read_first = 0;
|
||||||
u32 was_killed;
|
u32 was_killed;
|
||||||
|
u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
|
||||||
|
u32 tmp = version ^ 0xffffffff, status2, status = version;
|
||||||
|
u8 *msg = (u8 *)&status;
|
||||||
|
u8 *reply = (u8 *)&status2;
|
||||||
|
|
||||||
u8 child_stopped = 0;
|
u8 child_stopped = 0;
|
||||||
|
|
||||||
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) {
|
|
||||||
|
|
||||||
status_for_fsrv |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
status_for_fsrv |= FS_OPT_AUTODICT;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
|
|
||||||
if (status_for_fsrv) {
|
|
||||||
|
|
||||||
status_for_fsrv |= (FS_OPT_ENABLED | FS_OPT_NEWCMPLOG);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(tmp, &status_for_fsrv, 4);
|
|
||||||
|
|
||||||
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
/* 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. */
|
assume we're not running in forkserver mode and just execute program. */
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
|
// return because possible non-forkserver usage
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
|
||||||
|
|
||||||
__afl_connected = 1;
|
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
|
||||||
|
if (tmp != status2) {
|
||||||
|
|
||||||
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
|
write_error("wrong forkserver message from AFL++ tool");
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
|
}
|
||||||
|
|
||||||
if (__afl_debug) {
|
// send the set/requested options to forkserver
|
||||||
|
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
|
||||||
|
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
|
||||||
|
if (__afl_dictionary_len && __afl_dictionary) {
|
||||||
|
|
||||||
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
|
status |= FS_NEW_OPT_AUTODICT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// Now send the parameters for the set options, increasing by option number
|
||||||
|
|
||||||
|
// FS_NEW_OPT_MAPSIZE - we always send the map size
|
||||||
|
status = __afl_map_size;
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// FS_NEW_OPT_SHDMEM_FUZZ - no data
|
||||||
|
|
||||||
|
// FS_NEW_OPT_AUTODICT - send autodictionary
|
||||||
|
if (__afl_dictionary_len && __afl_dictionary) {
|
||||||
|
|
||||||
|
// pass the dictionary through the forkserver FD
|
||||||
|
u32 len = __afl_dictionary_len, offset = 0;
|
||||||
|
|
||||||
|
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
||||||
|
|
||||||
|
write(2, "Error: could not send dictionary len\n",
|
||||||
|
strlen("Error: could not send dictionary len\n"));
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
|
while (len != 0) {
|
||||||
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
|
|
||||||
|
|
||||||
__afl_map_shm_fuzz();
|
s32 ret;
|
||||||
|
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
||||||
|
|
||||||
}
|
if (ret < 1) {
|
||||||
|
|
||||||
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
|
write_error("could not send dictionary");
|
||||||
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
|
|
||||||
__afl_dictionary_len && __afl_dictionary) {
|
|
||||||
|
|
||||||
// great lets pass the dictionary through the forkserver FD
|
|
||||||
u32 len = __afl_dictionary_len, offset = 0;
|
|
||||||
|
|
||||||
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary len\n",
|
|
||||||
strlen("Error: could not send dictionary len\n"));
|
|
||||||
_exit(1);
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len != 0) {
|
len -= ret;
|
||||||
|
offset += ret;
|
||||||
s32 ret;
|
|
||||||
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
|
|
||||||
|
|
||||||
if (ret < 1) {
|
|
||||||
|
|
||||||
write(2, "Error: could not send dictionary\n",
|
|
||||||
strlen("Error: could not send dictionary\n"));
|
|
||||||
_exit(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= ret;
|
|
||||||
offset += ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// uh this forkserver does not understand extended option passing
|
|
||||||
// or does not want the dictionary
|
|
||||||
if (!__afl_fuzz_ptr) already_read_first = 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send welcome message as final message
|
||||||
|
status = version;
|
||||||
|
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
|
||||||
|
|
||||||
|
// END forkserver handshake
|
||||||
|
|
||||||
|
__afl_connected = 1;
|
||||||
|
|
||||||
|
if (__afl_sharedmem_fuzzing) { __afl_map_shm_fuzz(); }
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
@ -1229,7 +956,7 @@ static void __afl_start_forkserver(void) {
|
|||||||
|
|
||||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
|
||||||
|
|
||||||
// write_error("read from afl-fuzz");
|
write_error("read from AFL++ tool");
|
||||||
_exit(1);
|
_exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2234,7 +1961,8 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
|
void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2272,7 +2000,8 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
// fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
|
// fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2310,7 +2039,8 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
|
|||||||
|
|
||||||
// fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
|
// fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2353,7 +2083,8 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
|
|||||||
// (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
|
// (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
|
||||||
// attr);
|
// attr);
|
||||||
|
|
||||||
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (unlikely(arg1 == arg2 || size > __afl_cmplog_max_len)) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2397,6 +2128,7 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
|
|||||||
void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
|
void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
|
||||||
|
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
|
if (16 > __afl_cmplog_max_len) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2590,13 +2322,25 @@ void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
|
|
||||||
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!len)) return;
|
if (unlikely(!len || len > __afl_cmplog_max_len)) return;
|
||||||
int len0 = MIN(len, 31);
|
|
||||||
|
int len0 = MIN(len, 32);
|
||||||
|
|
||||||
int len1 = strnlen(ptr1, len0);
|
int len1 = strnlen(ptr1, len0);
|
||||||
if (len1 < 31) len1 = area_is_valid(ptr1, len1 + 1);
|
if (len1 <= 32) len1 = area_is_valid(ptr1, len1 + 1);
|
||||||
|
if (len1 > __afl_cmplog_max_len) len1 = 0;
|
||||||
|
|
||||||
int len2 = strnlen(ptr2, len0);
|
int len2 = strnlen(ptr2, len0);
|
||||||
if (len2 < 31) len2 = area_is_valid(ptr2, len2 + 1);
|
if (len2 <= 32) len2 = area_is_valid(ptr2, len2 + 1);
|
||||||
int l = MAX(len1, len2);
|
if (len2 > __afl_cmplog_max_len) len2 = 0;
|
||||||
|
|
||||||
|
int l;
|
||||||
|
if (!len1)
|
||||||
|
l = len2;
|
||||||
|
else if (!len2)
|
||||||
|
l = len1;
|
||||||
|
else
|
||||||
|
l = MAX(len1, len2);
|
||||||
if (l < 2) return;
|
if (l < 2) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
@ -2640,10 +2384,18 @@ void __cmplog_rtn_hook_str(u8 *ptr1, u8 *ptr2) {
|
|||||||
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!ptr1 || !ptr2)) return;
|
if (unlikely(!ptr1 || !ptr2)) return;
|
||||||
int len1 = strnlen(ptr1, 30) + 1;
|
int len1 = strnlen(ptr1, 31) + 1;
|
||||||
int len2 = strnlen(ptr2, 30) + 1;
|
int len2 = strnlen(ptr2, 31) + 1;
|
||||||
int l = MAX(len1, len2);
|
if (len1 > __afl_cmplog_max_len) len1 = 0;
|
||||||
if (l < 3) return;
|
if (len2 > __afl_cmplog_max_len) len2 = 0;
|
||||||
|
int l;
|
||||||
|
if (!len1)
|
||||||
|
l = len2;
|
||||||
|
else if (!len2)
|
||||||
|
l = len1;
|
||||||
|
else
|
||||||
|
l = MAX(len1, len2);
|
||||||
|
if (l < 2) return;
|
||||||
|
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
@ -2685,7 +2437,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
u32 i;
|
u32 i;
|
||||||
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
|
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
|
||||||
fprintf(stderr, "rtn arg0=");
|
fprintf(stderr, "rtn arg0=");
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
fprintf(stderr, "%02x", ptr1[i]);
|
fprintf(stderr, "%02x", ptr1[i]);
|
||||||
@ -2698,10 +2450,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
|
|||||||
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
int l1, l2;
|
int l1, l2;
|
||||||
if ((l1 = area_is_valid(ptr1, 31)) <= 0 ||
|
if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
|
||||||
(l2 = area_is_valid(ptr2, 31)) <= 0)
|
(l2 = area_is_valid(ptr2, 32)) <= 0)
|
||||||
return;
|
return;
|
||||||
int len = MIN(31, MIN(l1, l2));
|
int len = MIN(__afl_cmplog_max_len, MIN(l1, l2));
|
||||||
|
|
||||||
// fprintf(stderr, "RTN2 %u\n", len);
|
// fprintf(stderr, "RTN2 %u\n", len);
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
@ -2750,7 +2502,7 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
u32 i;
|
u32 i;
|
||||||
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
|
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
|
||||||
fprintf(stderr, "rtn_n len=%u arg0=", len);
|
fprintf(stderr, "rtn_n len=%u arg0=", len);
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
fprintf(stderr, "%02x", ptr1[i]);
|
fprintf(stderr, "%02x", ptr1[i]);
|
||||||
@ -2762,12 +2514,15 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
|
|||||||
|
|
||||||
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
|
||||||
if (likely(!__afl_cmp_map)) return;
|
if (likely(!__afl_cmp_map)) return;
|
||||||
if (unlikely(!len)) return;
|
if (!len) return;
|
||||||
int l = MIN(31, len);
|
int l = MIN(32, len), l1, l2;
|
||||||
|
|
||||||
if ((l = area_is_valid(ptr1, l)) <= 0 || (l = area_is_valid(ptr2, l)) <= 0)
|
if ((l1 = area_is_valid(ptr1, l)) <= 0 || (l2 = area_is_valid(ptr2, l)) <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
len = MIN(l1, l2);
|
||||||
|
if (len > __afl_cmplog_max_len) return;
|
||||||
|
|
||||||
// fprintf(stderr, "RTN2 %u\n", l);
|
// fprintf(stderr, "RTN2 %u\n", l);
|
||||||
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
uintptr_t k = (uintptr_t)__builtin_return_address(0);
|
||||||
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
|
||||||
|
13
src/afl-cc.c
13
src/afl-cc.c
@ -1148,12 +1148,16 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM)
|
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM &&
|
||||||
|
!((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
|
||||||
|
aflcc->compiler_mode == LTO))
|
||||||
FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
|
FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
|
||||||
|
|
||||||
if (aflcc->instrument_opt_mode &&
|
if (aflcc->instrument_opt_mode &&
|
||||||
aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
|
aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
|
||||||
aflcc->instrument_mode != INSTRUMENT_CLASSIC)
|
aflcc->instrument_mode != INSTRUMENT_CLASSIC &&
|
||||||
|
!(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER &&
|
||||||
|
aflcc->compiler_mode == LTO))
|
||||||
FATAL(
|
FATAL(
|
||||||
"CALLER, CTX and NGRAM instrumentation options can only be used with "
|
"CALLER, CTX and NGRAM instrumentation options can only be used with "
|
||||||
"the LLVM CLASSIC instrumentation mode.");
|
"the LLVM CLASSIC instrumentation mode.");
|
||||||
@ -2917,11 +2921,12 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
|||||||
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
|
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
|
||||||
"functions\n"
|
"functions\n"
|
||||||
" into this file (LTO mode)\n"
|
" into this file (LTO mode)\n"
|
||||||
|
" AFL_LLVM_LTO_CALLER: activate CALLER/CTX instrumentation\n"
|
||||||
|
" AFL_LLVM_LTO_CALLER_DEPTH: skip how many empty functions\n"
|
||||||
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
|
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
|
||||||
"global var\n"
|
"global var\n"
|
||||||
" AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
|
" AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
|
||||||
"a "
|
"a bb\n"
|
||||||
"bb\n"
|
|
||||||
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
||||||
"path\n"
|
"path\n"
|
||||||
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
|
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
|
||||||
|
@ -389,7 +389,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
uint32_t was_killed;
|
uint32_t was_killed;
|
||||||
int status;
|
u32 status;
|
||||||
|
|
||||||
/* Wait for parent by reading from the pipe. Exit if read fails. */
|
/* Wait for parent by reading from the pipe. Exit if read fails. */
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
volatile u8 *stop_soon_p, u8 debug_child_output) {
|
volatile u8 *stop_soon_p, u8 debug_child_output) {
|
||||||
|
|
||||||
int st_pipe[2], ctl_pipe[2];
|
int st_pipe[2], ctl_pipe[2];
|
||||||
s32 status;
|
u32 status;
|
||||||
s32 rlen;
|
s32 rlen;
|
||||||
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
|
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
|
||||||
|
|
||||||
@ -1017,83 +1017,68 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
if (rlen == 4) {
|
if (rlen == 4) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The new fork server model works like this:
|
||||||
|
* Client: sends "AFLx" in little endian, with x being the forkserver
|
||||||
|
* protocol version.
|
||||||
|
* Server: replies with XOR of the message or exits with an error if it
|
||||||
|
* is not a supported version.
|
||||||
|
* Client: sends 32 bit of options and then sends all parameters of
|
||||||
|
* the options, one after another, increasing by option number.
|
||||||
|
* Ends with "AFLx".
|
||||||
|
* After the initial protocol version confirmation the server does not
|
||||||
|
* send any data anymore - except a future option requires this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((status & FS_NEW_ERROR) == FS_NEW_ERROR) {
|
||||||
|
|
||||||
|
report_error_and_exit(status & 0x0000ffff);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (status >= 0x41464c00 && status <= 0x41464cff) {
|
if (status >= 0x41464c00 && status <= 0x41464cff) {
|
||||||
|
|
||||||
FATAL(
|
u32 version = status - 0x41464c00;
|
||||||
"Target uses the new forkserver model, you need to switch to a newer "
|
|
||||||
"afl-fuzz too!");
|
|
||||||
|
|
||||||
}
|
if (!version) {
|
||||||
|
|
||||||
if (!be_quiet) { OKF("All right - fork server is up."); }
|
FATAL(
|
||||||
|
"Fork server version is not assigned, this should not happen. "
|
||||||
|
"Recompile target.");
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG")) {
|
} else if (version < FS_NEW_VERSION_MIN || version > FS_NEW_VERSION_MAX) {
|
||||||
|
|
||||||
ACTF("Extended forkserver functions received (%08x).", status);
|
FATAL(
|
||||||
|
"Fork server version is not not supported. Recompile the target.");
|
||||||
}
|
|
||||||
|
|
||||||
if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
|
|
||||||
report_error_and_exit(FS_OPT_GET_ERROR(status));
|
|
||||||
|
|
||||||
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
|
||||||
|
|
||||||
// workaround for recent AFL++ versions
|
|
||||||
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
|
|
||||||
status = (status & 0xf0ffffff);
|
|
||||||
|
|
||||||
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
|
|
||||||
|
|
||||||
if (fsrv->qemu_mode || fsrv->frida_mode) {
|
|
||||||
|
|
||||||
report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
report_error_and_exit(FS_ERROR_OLD_CMPLOG);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
|
u32 keep = status;
|
||||||
|
status ^= 0xffffffff;
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
fsrv->snapshot = 1;
|
FATAL("Writing to forkserver failed.");
|
||||||
if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
|
if (!be_quiet) {
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz) {
|
OKF("All right - new fork server model v%u is up.", version);
|
||||||
|
|
||||||
fsrv->use_shmem_fuzz = 1;
|
|
||||||
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
|
||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
|
|
||||||
|
|
||||||
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
|
||||||
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Writing to forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
FATAL(
|
|
||||||
"Target requested sharedmem fuzzing, but we failed to enable "
|
|
||||||
"it.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
rlen = read(fsrv->fsrv_st_fd, &status, 4);
|
||||||
|
|
||||||
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
|
ACTF("Forkserver options received: (0x%08x)", status);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_NEW_OPT_MAPSIZE)) {
|
||||||
|
|
||||||
|
u32 tmp_map_size;
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, &tmp_map_size, 4);
|
||||||
|
|
||||||
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
||||||
|
|
||||||
@ -1110,7 +1095,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
FATAL(
|
FATAL(
|
||||||
"Target's coverage map size of %u is larger than the one this "
|
"Target's coverage map size of %u is larger than the one this "
|
||||||
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
|
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
|
||||||
|
"restart "
|
||||||
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
||||||
"afl-fuzz",
|
"afl-fuzz",
|
||||||
tmp_map_size, fsrv->map_size, tmp_map_size);
|
tmp_map_size, fsrv->map_size, tmp_map_size);
|
||||||
@ -1119,22 +1105,242 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
fsrv->map_size = tmp_map_size;
|
fsrv->map_size = tmp_map_size;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fsrv->real_map_size = fsrv->map_size = MAP_SIZE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) {
|
||||||
|
|
||||||
if (!ignore_autodict) {
|
if (fsrv->support_shmem_fuzz) {
|
||||||
|
|
||||||
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
fsrv->use_shmem_fuzz = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Target requested sharedmem fuzzing, but we failed to enable "
|
||||||
|
"it.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_NEW_OPT_AUTODICT)) {
|
||||||
|
|
||||||
|
u32 dict_size;
|
||||||
|
if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Reading from forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict_size < 2 || dict_size > 0xffffff) {
|
||||||
|
|
||||||
|
FATAL("Dictionary has an illegal size: %d", dict_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 offset = 0, count = 0;
|
||||||
|
u8 *dict = ck_alloc(dict_size);
|
||||||
|
if (dict == NULL) {
|
||||||
|
|
||||||
|
FATAL("Could not allocate %u bytes of autodictionary memory",
|
||||||
|
dict_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (dict_size != 0) {
|
||||||
|
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size);
|
||||||
|
if (rlen > 0) {
|
||||||
|
|
||||||
|
dict_size -= rlen;
|
||||||
|
offset += rlen;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Reading autodictionary fail at position %u with %u bytes "
|
||||||
|
"left.",
|
||||||
|
offset, dict_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
|
||||||
|
|
||||||
|
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||||
|
(u8)dict[offset]);
|
||||||
|
offset += (1 + dict[offset]);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
||||||
|
ck_free(dict);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 status2;
|
||||||
|
rlen = read(fsrv->fsrv_st_fd, &status2, 4);
|
||||||
|
|
||||||
|
if (status2 != keep) {
|
||||||
|
|
||||||
|
FATAL("Error in forkserver communication (%08x=>%08x)", keep, status2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
WARNF(
|
||||||
|
"Old fork server model is used by the target, this still works "
|
||||||
|
"though.");
|
||||||
|
|
||||||
|
if (!be_quiet) { OKF("All right - old fork server is up."); }
|
||||||
|
|
||||||
|
if (getenv("AFL_DEBUG")) {
|
||||||
|
|
||||||
|
ACTF("Extended forkserver functions received (%08x).", status);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
|
||||||
|
report_error_and_exit(FS_OPT_GET_ERROR(status));
|
||||||
|
|
||||||
|
if (fsrv->cmplog_binary) {
|
||||||
|
|
||||||
|
FATAL("Target was recompiled with outdated CMPLOG, recompile it!\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
|
||||||
|
|
||||||
|
// workaround for recent AFL++ versions
|
||||||
|
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) ==
|
||||||
|
FS_OPT_OLD_AFLPP_WORKAROUND)
|
||||||
|
status = (status & 0xf0ffffff);
|
||||||
|
|
||||||
|
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
|
||||||
|
|
||||||
|
if (fsrv->qemu_mode || fsrv->frida_mode) {
|
||||||
|
|
||||||
|
report_error_and_exit(FS_ERROR_OLD_CMPLOG_QEMU);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
report_error_and_exit(FS_ERROR_OLD_CMPLOG);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
|
||||||
|
|
||||||
|
fsrv->snapshot = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) {
|
||||||
|
|
||||||
|
if (fsrv->support_shmem_fuzz) {
|
||||||
|
|
||||||
|
fsrv->use_shmem_fuzz = 1;
|
||||||
|
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
|
||||||
|
|
||||||
|
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
|
||||||
|
|
||||||
|
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Writing to forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Target requested sharedmem fuzzing, but we failed to enable "
|
||||||
|
"it.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) {
|
||||||
|
|
||||||
|
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
|
||||||
|
|
||||||
|
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
|
||||||
|
|
||||||
|
fsrv->real_map_size = tmp_map_size;
|
||||||
|
|
||||||
|
if (tmp_map_size % 64) {
|
||||||
|
|
||||||
|
tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_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 set with (%u). Either set AFL_MAP_SIZE=%u and "
|
||||||
|
"restart "
|
||||||
|
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
|
||||||
|
"afl-fuzz",
|
||||||
|
tmp_map_size, fsrv->map_size, tmp_map_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fsrv->map_size = tmp_map_size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
|
||||||
|
|
||||||
|
if (!ignore_autodict) {
|
||||||
|
|
||||||
|
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
|
||||||
|
|
||||||
|
// this is not afl-fuzz - or it is cmplog - we deny and return
|
||||||
|
if (fsrv->use_shmem_fuzz) {
|
||||||
|
|
||||||
|
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
status = (FS_OPT_ENABLED);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
|
FATAL("Writing to forkserver failed.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
|
||||||
|
|
||||||
// this is not afl-fuzz - or it is cmplog - we deny and return
|
|
||||||
if (fsrv->use_shmem_fuzz) {
|
if (fsrv->use_shmem_fuzz) {
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED);
|
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,82 +1350,63 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
|
||||||
|
|
||||||
}
|
FATAL("Reading from forkserver failed.");
|
||||||
|
|
||||||
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
|
|
||||||
|
|
||||||
if (fsrv->use_shmem_fuzz) {
|
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Writing to forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
|
|
||||||
|
|
||||||
FATAL("Reading from forkserver failed.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status < 2 || (u32)status > 0xffffff) {
|
|
||||||
|
|
||||||
FATAL("Dictionary has an illegal size: %d", status);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = 0, count = 0;
|
|
||||||
u32 len = status;
|
|
||||||
u8 *dict = ck_alloc(len);
|
|
||||||
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);
|
|
||||||
if (rlen > 0) {
|
|
||||||
|
|
||||||
len -= rlen;
|
|
||||||
offset += rlen;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
FATAL(
|
|
||||||
"Reading autodictionary fail at position %u with %u bytes "
|
|
||||||
"left.",
|
|
||||||
offset, len);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (status < 2 || (u32)status > 0xffffff) {
|
||||||
|
|
||||||
offset = 0;
|
FATAL("Dictionary has an illegal size: %d", status);
|
||||||
while (offset < (u32)status &&
|
|
||||||
(u8)dict[offset] + offset < (u32)status) {
|
|
||||||
|
|
||||||
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
}
|
||||||
(u8)dict[offset]);
|
|
||||||
offset += (1 + dict[offset]);
|
u32 offset = 0, count = 0;
|
||||||
count++;
|
u32 len = status;
|
||||||
|
u8 *dict = ck_alloc(len);
|
||||||
|
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);
|
||||||
|
if (rlen > 0) {
|
||||||
|
|
||||||
|
len -= rlen;
|
||||||
|
offset += rlen;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
FATAL(
|
||||||
|
"Reading autodictionary fail at position %u with %u bytes "
|
||||||
|
"left.",
|
||||||
|
offset, len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
while (offset < (u32)status &&
|
||||||
|
(u8)dict[offset] + offset < (u32)status) {
|
||||||
|
|
||||||
|
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||||
|
(u8)dict[offset]);
|
||||||
|
offset += (1 + dict[offset]);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
||||||
|
ck_free(dict);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
|
||||||
ck_free(dict);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||||
|
|
||||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
Copyright 2019-2023 AFLplusplus Project. All rights reserved.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -87,6 +87,11 @@ static u32 hshape;
|
|||||||
static u64 screen_update;
|
static u64 screen_update;
|
||||||
static u64 last_update;
|
static u64 last_update;
|
||||||
|
|
||||||
|
// hashmap functions
|
||||||
|
void hashmap_reset();
|
||||||
|
bool hashmap_search_and_add(uint8_t type, uint64_t key);
|
||||||
|
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key);
|
||||||
|
|
||||||
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
|
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
|
||||||
|
|
||||||
struct range *r = ck_alloc_nozero(sizeof(struct range));
|
struct range *r = ck_alloc_nozero(sizeof(struct range));
|
||||||
@ -795,7 +800,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
u64 *o_buf_64 = (u64 *)&orig_buf[idx];
|
u64 *o_buf_64 = (u64 *)&orig_buf[idx];
|
||||||
u32 *o_buf_32 = (u32 *)&orig_buf[idx];
|
u32 *o_buf_32 = (u32 *)&orig_buf[idx];
|
||||||
u16 *o_buf_16 = (u16 *)&orig_buf[idx];
|
u16 *o_buf_16 = (u16 *)&orig_buf[idx];
|
||||||
u8 *o_buf_8 = &orig_buf[idx];
|
// u8 *o_buf_8 = &orig_buf[idx];
|
||||||
|
|
||||||
u32 its_len = MIN(len - idx, taint_len);
|
u32 its_len = MIN(len - idx, taint_len);
|
||||||
|
|
||||||
@ -836,6 +841,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
// necessary for preventing heap access overflow
|
// necessary for preventing heap access overflow
|
||||||
bytes = MIN(bytes, len - idx);
|
bytes = MIN(bytes, len - idx);
|
||||||
|
if (unlikely(bytes <= 1)) { return 0; }
|
||||||
|
|
||||||
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
|
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
|
||||||
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
|
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
|
||||||
@ -1266,6 +1272,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (*status != 1) { // u8
|
if (*status != 1) { // u8
|
||||||
|
|
||||||
// if (its_len >= 1)
|
// if (its_len >= 1)
|
||||||
@ -1290,6 +1297,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If 'S' is set for cmplog mode then we try a scale encoding of the value.
|
// If 'S' is set for cmplog mode then we try a scale encoding of the value.
|
||||||
@ -1881,6 +1890,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
hshape = SHAPE_BYTES(h->shape);
|
hshape = SHAPE_BYTES(h->shape);
|
||||||
|
|
||||||
|
if (hshape < 2) { return 0; }
|
||||||
|
|
||||||
if (h->hits > CMP_MAP_H) {
|
if (h->hits > CMP_MAP_H) {
|
||||||
|
|
||||||
loggeds = CMP_MAP_H;
|
loggeds = CMP_MAP_H;
|
||||||
@ -1906,8 +1917,6 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hshape < 2) { return 0; }
|
|
||||||
|
|
||||||
for (i = 0; i < loggeds; ++i) {
|
for (i = 0; i < loggeds; ++i) {
|
||||||
|
|
||||||
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
|
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
|
||||||
@ -1945,6 +1954,16 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add attribute? not sure
|
||||||
|
if (hshape <= 8 && hashmap_search_and_add(hshape - 1, o->v0) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, orig_o->v0) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, o->v1) &&
|
||||||
|
hashmap_search_and_add(hshape - 1, orig_o->v1)) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
|
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
|
||||||
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
|
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, hshape);
|
||||||
@ -2219,15 +2238,15 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
|
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 32 || l1 > 32 ||
|
||||||
ol0 > 31 || ol1 > 31) {
|
ol0 > 32 || ol1 > 32) {
|
||||||
|
|
||||||
l0 = ol0 = hshape;
|
l0 = ol0 = hshape;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 lmax = MAX(l0, ol0);
|
u8 lmax = MAX(l0, ol0);
|
||||||
u8 save[40];
|
u8 save[80];
|
||||||
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
|
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
|
||||||
u32 its_len = MIN(MIN(lmax, hshape), len - idx);
|
u32 its_len = MIN(MIN(lmax, hshape), len - idx);
|
||||||
its_len = MIN(its_len, taint_len);
|
its_len = MIN(its_len, taint_len);
|
||||||
@ -2330,7 +2349,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
u32 tob64 = 0, fromb64 = 0;
|
u32 tob64 = 0, fromb64 = 0;
|
||||||
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
|
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
|
||||||
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
|
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
|
||||||
u8 xor_val[32], arith_val[32], tmp[48];
|
u8 xor_val[64], arith_val[64], tmp[64];
|
||||||
|
|
||||||
idx = saved_idx;
|
idx = saved_idx;
|
||||||
its_len = saved_its_len;
|
its_len = saved_its_len;
|
||||||
@ -2615,12 +2634,13 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buf + idx, tmp, hlen + 1 + off);
|
u32 tmp_l = hlen + 1 + off;
|
||||||
|
memcpy(buf + idx, tmp, tmp_l);
|
||||||
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
|
||||||
tmp[hlen + 1 + off] = 0;
|
tmp[tmp_l] = 0;
|
||||||
// fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
|
// fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
|
||||||
// %u\n", idx, len, fromhex, tmp, repl, *status);
|
// %u\n", idx, len, fromhex, tmp, repl, *status);
|
||||||
memcpy(buf + idx, save, hlen + 1 + off);
|
memcpy(buf + idx, save, tmp_l);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2755,6 +2775,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hshape <= 8 && hashmap_search_and_add_ptr(hshape - 1, o->v0) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, o->v1) &&
|
||||||
|
hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) {
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
t = taint;
|
t = taint;
|
||||||
while (t->next) {
|
while (t->next) {
|
||||||
|
|
||||||
@ -3021,6 +3050,8 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
|||||||
|
|
||||||
// Start insertion loop
|
// Start insertion loop
|
||||||
|
|
||||||
|
hashmap_reset();
|
||||||
|
|
||||||
u64 orig_hit_cnt, new_hit_cnt;
|
u64 orig_hit_cnt, new_hit_cnt;
|
||||||
u64 orig_execs = afl->fsrv.total_execs;
|
u64 orig_execs = afl->fsrv.total_execs;
|
||||||
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
||||||
|
@ -102,7 +102,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
|
|||||||
afl->stats_update_freq = 1;
|
afl->stats_update_freq = 1;
|
||||||
afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
|
afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
|
||||||
afl->stats_avg_exec = 0;
|
afl->stats_avg_exec = 0;
|
||||||
afl->skip_deterministic = 1;
|
afl->skip_deterministic = 0;
|
||||||
afl->sync_time = SYNC_TIME;
|
afl->sync_time = SYNC_TIME;
|
||||||
afl->cmplog_lvl = 2;
|
afl->cmplog_lvl = 2;
|
||||||
afl->min_length = 1;
|
afl->min_length = 1;
|
||||||
|
@ -1112,7 +1112,7 @@ void show_stats_normal(afl_state_t *afl) {
|
|||||||
|
|
||||||
} else if (likely(afl->skip_deterministic)) {
|
} else if (likely(afl->skip_deterministic)) {
|
||||||
|
|
||||||
strcpy(tmp, "disabled (default, enable with -D)");
|
strcpy(tmp, "disabled (-z switch used)");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -170,7 +170,6 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
" -g minlength - set min length of generated fuzz input (default: 1)\n"
|
" -g minlength - set min length of generated fuzz input (default: 1)\n"
|
||||||
" -G maxlength - set max length of generated fuzz input (default: "
|
" -G maxlength - set max length of generated fuzz input (default: "
|
||||||
"%lu)\n"
|
"%lu)\n"
|
||||||
" -D - enable (a new) effective deterministic fuzzing\n"
|
|
||||||
" -L minutes - use MOpt(imize) mode and set the time limit for "
|
" -L minutes - use MOpt(imize) mode and set the time limit for "
|
||||||
"entering the\n"
|
"entering the\n"
|
||||||
" pacemaker mode (minutes of no new finds). 0 = "
|
" pacemaker mode (minutes of no new finds). 0 = "
|
||||||
@ -213,7 +212,8 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
" -F path - sync to a foreign fuzzer queue directory (requires "
|
" -F path - sync to a foreign fuzzer queue directory (requires "
|
||||||
"-M, can\n"
|
"-M, can\n"
|
||||||
" be specified up to %u times)\n"
|
" be specified up to %u times)\n"
|
||||||
// " -d - skip deterministic fuzzing in -M mode\n"
|
" -z - skip the enhanced deterministic fuzzing\n"
|
||||||
|
" (note that the old -d and -D flags are ignored.)\n"
|
||||||
" -T text - text banner to show on the screen\n"
|
" -T text - text banner to show on the screen\n"
|
||||||
" -I command - execute this command/script when a new crash is "
|
" -I command - execute this command/script when a new crash is "
|
||||||
"found\n"
|
"found\n"
|
||||||
@ -543,7 +543,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
// still available: HjJkKqruvwz
|
// still available: HjJkKqruvwz
|
||||||
while ((opt = getopt(argc, argv,
|
while ((opt = getopt(argc, argv,
|
||||||
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
||||||
"T:UV:WXx:YZ")) > 0) {
|
"T:UV:WXx:YzZ")) > 0) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -959,20 +959,17 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D': /* partial deterministic */
|
case 'd':
|
||||||
|
case 'D': /* old deterministic */
|
||||||
|
|
||||||
afl->skip_deterministic = 0;
|
WARNF(
|
||||||
|
"Parameters -d and -D are deprecated, a new enhanced deterministic "
|
||||||
|
"fuzzing is active by default, to disable it use -z");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': /* no deterministic */
|
case 'z': /* no deterministic */
|
||||||
|
|
||||||
// this is the default and currently a lot of infrastructure enforces
|
afl->skip_deterministic = 1;
|
||||||
// it (e.g. clusterfuzz, fuzzbench) based on that this feature
|
|
||||||
// originally was bad performance wise. We now have a better
|
|
||||||
// implementation, hence if it is activated, we do not want to
|
|
||||||
// deactivate it by such setups.
|
|
||||||
|
|
||||||
// afl->skip_deterministic = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B': /* load bitmap */
|
case 'B': /* load bitmap */
|
||||||
|
149
src/hashmap.c
Normal file
149
src/hashmap.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
#define TABLE_SIZE 10007 // Use a prime number for better distribution
|
||||||
|
|
||||||
|
typedef struct HashNode {
|
||||||
|
|
||||||
|
uint64_t key;
|
||||||
|
struct HashNode *next;
|
||||||
|
|
||||||
|
} HashNode;
|
||||||
|
|
||||||
|
typedef struct HashMap {
|
||||||
|
|
||||||
|
HashNode **table;
|
||||||
|
|
||||||
|
} HashMap;
|
||||||
|
|
||||||
|
static HashMap *_hashmap;
|
||||||
|
|
||||||
|
void hashmap_reset() {
|
||||||
|
|
||||||
|
if (unlikely(!_hashmap)) {
|
||||||
|
|
||||||
|
_hashmap = (HashMap *)malloc(sizeof(HashMap));
|
||||||
|
_hashmap->table = (HashNode **)malloc(sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (int i = 0; i < TABLE_SIZE; i++) {
|
||||||
|
|
||||||
|
HashNode *node = _hashmap->table[i];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
HashNode *temp = node;
|
||||||
|
node = node->next;
|
||||||
|
free(temp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int hash(uint64_t key) {
|
||||||
|
|
||||||
|
return key % TABLE_SIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// type must be below 8
|
||||||
|
bool hashmap_search_and_add(uint8_t type, uint64_t key) {
|
||||||
|
|
||||||
|
if (unlikely(type >= 8)) return false;
|
||||||
|
uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56);
|
||||||
|
unsigned int index = hash(val);
|
||||||
|
HashNode *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == val) return true;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found so add it
|
||||||
|
node = (HashNode *)malloc(sizeof(HashNode));
|
||||||
|
node->key = val;
|
||||||
|
node->next = _hashmap->table[index];
|
||||||
|
_hashmap->table[index] = node;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// type must be below 8
|
||||||
|
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key) {
|
||||||
|
|
||||||
|
if (unlikely(type >= 8)) return false;
|
||||||
|
uint64_t key_t = 0;
|
||||||
|
memcpy(((char *)key_t) + (7 - type), key, type + 1);
|
||||||
|
return hashmap_search_and_add(type, key_t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* below is not used */
|
||||||
|
|
||||||
|
void hashmap_insert(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *node = (HashNode *)malloc(sizeof(HashNode));
|
||||||
|
node->key = key;
|
||||||
|
node->next = _hashmap->table[index];
|
||||||
|
_hashmap->table[index] = node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hashmap_search(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == key) return true;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete(uint64_t key) {
|
||||||
|
|
||||||
|
unsigned int index = hash(key);
|
||||||
|
HashNode *prev = NULL, *node = _hashmap->table[index];
|
||||||
|
while (node) {
|
||||||
|
|
||||||
|
if (node->key == key) {
|
||||||
|
|
||||||
|
if (prev)
|
||||||
|
prev->next = node->next;
|
||||||
|
else
|
||||||
|
_hashmap->table[index] = node->next;
|
||||||
|
free(node);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeHashMap(HashMap *map) {
|
||||||
|
|
||||||
|
free(_hashmap->table);
|
||||||
|
free(map);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
|||||||
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
|
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
|
||||||
CODE=1
|
CODE=1
|
||||||
}
|
}
|
||||||
rm -f test-instr.ts.0 test-instr.ts.1
|
rm -f test-instr.ts.0 test-instr.ts.1 test-instr.ts
|
||||||
} || {
|
} || {
|
||||||
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
|
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
|
||||||
CODE=1
|
CODE=1
|
||||||
|
Reference in New Issue
Block a user