mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-19 13:03:44 +00:00
skip entried synced from us if we have not restarted
This commit is contained in:
@ -1259,6 +1259,7 @@ int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen);
|
||||
|
||||
/* Run */
|
||||
|
||||
void check_sync_fuzzers(afl_state_t *);
|
||||
void sync_fuzzers(afl_state_t *);
|
||||
u32 write_to_testcase(afl_state_t *, void **, u32, u32);
|
||||
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
|
||||
|
@ -699,42 +699,105 @@ abort_calibration:
|
||||
|
||||
}
|
||||
|
||||
bool is_known_case(afl_state_t *afl, u8 *name, void *mem, u32 len) {
|
||||
/* Do not sync items that were synced from us */
|
||||
|
||||
static bool is_known_case(afl_state_t *afl, u8 *name) {
|
||||
|
||||
static char coming_from_me_str[SYNC_ID_MAX_LEN + 2];
|
||||
static u32 coming_from_me_len = 0;
|
||||
static u32 min_len = 15 + 4 + 6;
|
||||
|
||||
static char coming_from_me_str[16 + SYNC_ID_MAX_LEN];
|
||||
static int coming_from_me_len = 0;
|
||||
if (!coming_from_me_len) {
|
||||
|
||||
snprintf(coming_from_me_str, sizeof(coming_from_me_str),
|
||||
",sync:%s,src:", afl->sync_id);
|
||||
coming_from_me_len = strlen(coming_from_me_str);
|
||||
snprintf(coming_from_me_str, sizeof(coming_from_me_str), "%s,",
|
||||
afl->sync_id);
|
||||
min_len += coming_from_me_len = strlen(coming_from_me_str);
|
||||
|
||||
}
|
||||
|
||||
// 9 = strlen("id:000000"), 6 = strlen("000000")
|
||||
if (strlen(name) < 9 + coming_from_me_len + 6) return false;
|
||||
char *p = name + 9;
|
||||
while ('0' <= *p && *p <= '9')
|
||||
p++;
|
||||
// file name length long enough so it can be ours
|
||||
if (unlikely(strlen(name) < min_len)) { return false; }
|
||||
// is it based on a sync? allow optimizer to make an integer comparison
|
||||
if (likely(memcmp(name + 10, "sync", 4) != 0)) { return false; }
|
||||
// we jump over the ':' after 'sync' and compare to our sync name
|
||||
if (unlikely(memcmp(name + 15, coming_from_me_str, coming_from_me_len) !=
|
||||
0)) {
|
||||
|
||||
if (strncmp(p, coming_from_me_str, coming_from_me_len) != 0) return false;
|
||||
return false;
|
||||
|
||||
int src_id = atoi(p + coming_from_me_len);
|
||||
if (src_id < 0 || src_id >= afl->queued_items) return false;
|
||||
}
|
||||
|
||||
struct queue_entry *q = afl->queue_buf[src_id];
|
||||
if (q->len != len) return false;
|
||||
/* We do not need this as we now look on startup how many files are in sync
|
||||
targets.
|
||||
int src_id = atoi(name + 15 + coming_from_me_len + 4);
|
||||
if (unlikely(src_id >= afl->queued_items)) return false;
|
||||
*/
|
||||
|
||||
if (q->testcase_buf) return memcmp(q->testcase_buf, mem, len) == 0;
|
||||
// yes it is highly likely a current testcase we already know
|
||||
return true;
|
||||
|
||||
int fd = open((char *)q->fname, O_RDONLY);
|
||||
if (fd < 0) return false;
|
||||
u8 *buf = malloc(len);
|
||||
ck_read(fd, buf, len, q->fname);
|
||||
close(fd);
|
||||
bool result = (memcmp(buf, mem, len) == 0);
|
||||
free(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
void check_sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
if (unlikely(afl->afl_env.afl_no_sync)) { return; }
|
||||
|
||||
DIR *sd, *dir;
|
||||
struct dirent *sd_ent, *entry;
|
||||
u8 qd_path[PATH_MAX], qd_synced_maxid[PATH_MAX];
|
||||
|
||||
sd = opendir(afl->sync_dir);
|
||||
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
|
||||
|
||||
u64 sync_start_us = get_cur_time_us();
|
||||
// Look at the entries created for every other fuzzer in the sync directory.
|
||||
|
||||
while ((sd_ent = readdir(sd))) {
|
||||
|
||||
if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
sprintf(qd_path, "%s/%s/queue", afl->sync_dir, sd_ent->d_name);
|
||||
|
||||
dir = opendir(qd_path);
|
||||
if (dir) {
|
||||
|
||||
u32 max_start_id = 0;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
|
||||
max_start_id++;
|
||||
|
||||
}
|
||||
|
||||
if (max_start_id > 4) {
|
||||
|
||||
sprintf(qd_synced_maxid, "%s/.synced/%s.max", afl->out_dir,
|
||||
sd_ent->d_name);
|
||||
s32 max_fd = open(qd_synced_maxid, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
DEFAULT_PERMISSION);
|
||||
|
||||
if (max_fd >= 0) {
|
||||
|
||||
max_start_id -= 4; // without ".", "..", ".state" and counting from 0
|
||||
write(max_fd, &max_start_id, sizeof(u32));
|
||||
close(max_fd);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
}
|
||||
|
||||
closedir(sd);
|
||||
|
||||
update_sync_time(afl, &sync_start_us);
|
||||
|
||||
}
|
||||
|
||||
@ -764,9 +827,8 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
// iteration
|
||||
update_sync_time(afl, &sync_start_us);
|
||||
|
||||
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
|
||||
u32 min_accept = 0, next_min_accept = 0;
|
||||
|
||||
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX], qd_synced_maxid[PATH_MAX];
|
||||
u32 min_accept = 0, next_min_accept = 0, max_start_id = 0;
|
||||
s32 id_fd;
|
||||
|
||||
// Skip dot files and our own output directory.
|
||||
@ -851,17 +913,19 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
snprintf(id0, sizeof(id0), "%s/id:000000,*", qd_path);
|
||||
|
||||
if (glob(id0, 0, NULL, &glob_result) == 0 && glob_result.gl_pathc == 1 &&
|
||||
stat(glob_result.gl_pathv[0], &st) == 0) {
|
||||
if (likely(glob(id0, 0, NULL, &glob_result) == 0 &&
|
||||
glob_result.gl_pathc == 1 &&
|
||||
stat(glob_result.gl_pathv[0], &st) == 0)) {
|
||||
|
||||
// we found exactly one "id:000000,*" file and obtained its mtime
|
||||
globfree(&glob_result);
|
||||
|
||||
if (last_mtime && last_mtime < st.st_mtime) {
|
||||
if (unlikely(last_mtime && last_mtime < st.st_mtime)) {
|
||||
|
||||
// the first entry is newer than when we synced last - instance was
|
||||
// restarted - we have to reset our counter and will skip this instance
|
||||
// this time
|
||||
// this time. It could also be this was trimmed later, or restated with
|
||||
// resume-in-place though but better be safe.
|
||||
min_accept = 0;
|
||||
ck_write(id_fd, &min_accept, sizeof(u32), qd_synced_path);
|
||||
goto close_sync;
|
||||
@ -877,6 +941,18 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
// check if there is a file documented the maximum id seen on startup
|
||||
sprintf(qd_synced_maxid, "%s/.synced/%s.max", afl->out_dir, sd_ent->d_name);
|
||||
s32 max_fd = open(qd_synced_maxid, O_RDONLY, DEFAULT_PERMISSION);
|
||||
|
||||
if (max_fd >= 0) {
|
||||
|
||||
read(max_fd, &max_start_id, sizeof(u32));
|
||||
close(max_fd);
|
||||
if (max_start_id < next_min_accept) { unlink(qd_synced_maxid); }
|
||||
|
||||
}
|
||||
|
||||
/* Show stats */
|
||||
|
||||
snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "sync %u", ++sync_cnt);
|
||||
@ -930,19 +1006,19 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
if (st.st_size && st.st_size <= MAX_FILE) {
|
||||
|
||||
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 (!is_known_case(afl, namelist[o]->d_name, mem, st.st_size)) {
|
||||
if (likely(next_min_accept < max_start_id ||
|
||||
!is_known_case(afl, namelist[o]->d_name))) {
|
||||
|
||||
/* See what happens. We rely on save_if_interesting() to catch major
|
||||
errors and save the test case. */
|
||||
|
||||
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (mem == MAP_FAILED) { PFATAL("Unable to mmap '%s'", path); }
|
||||
|
||||
u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
u8 fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) {
|
||||
|
||||
@ -957,11 +1033,10 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
|
||||
show_stats(afl);
|
||||
afl->syncing_party = 0;
|
||||
munmap(mem, st.st_size);
|
||||
|
||||
}
|
||||
|
||||
munmap(mem, st.st_size);
|
||||
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
@ -2998,6 +2998,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (afl->stop_soon) { goto stop_fuzzing; }
|
||||
|
||||
if (!afl->in_place_resume) { check_sync_fuzzers(afl); }
|
||||
|
||||
/* Woop woop woop */
|
||||
|
||||
if (!afl->not_on_tty) {
|
||||
|
Reference in New Issue
Block a user