afl-cmin/afl-cmin.bash/afl-showmap -i descend into subdirectories

This commit is contained in:
vanhauser-thc
2021-06-16 11:46:26 +02:00
parent f3362007ed
commit a6c0b5f766
2 changed files with 96 additions and 65 deletions

View File

@ -31,6 +31,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- afl_analyze:
- fix timeout handling
- add forkserver support for better performance
- afl-cmin, afl-cmin.bash and afl-showmap -i do now descend into
subdirectories (like afl-fuzz does)
- ensure afl-compiler-rt is built for gcc_module
### Version ++3.13c (release)

View File

@ -67,6 +67,8 @@ static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
static u8 outfile[PATH_MAX];
static u8 *in_data, /* Input data */
*coverage_map; /* Coverage map */
@ -88,7 +90,8 @@ static bool quiet_mode, /* Hide non-essential messages? */
have_coverage, /* have coverage? */
no_classify, /* do not classify counts */
debug, /* debug mode */
print_filenames; /* print the current filename */
print_filenames, /* print the current filename */
wait_for_gdb;
static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_crashed; /* Child crashed? */
@ -692,6 +695,93 @@ static void setup_signal_handlers(void) {
}
u32 execute_testcases(u8 *dir) {
struct dirent **nl;
s32 nl_cnt, subdirs = 1;
u32 i, done = 0;
u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
if (!be_quiet) { ACTF("Scanning '%s'...", dir); }
/* We use scandir() + alphasort() rather than readdir() because otherwise,
the ordering of test cases would vary somewhat randomly and would be
difficult to control. */
nl_cnt = scandir(dir, &nl, NULL, alphasort);
if (nl_cnt < 0) { return 0; }
for (i = 0; i < (u32)nl_cnt; ++i) {
struct stat st;
u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
if (lstat(fn2, &st) || access(fn2, R_OK)) {
PFATAL("Unable to access '%s'", fn2);
}
/* obviously we want to skip "descending" into . and .. directories,
however it is a good idea to skip also directories that start with
a dot */
if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
free(nl[i]); /* not tracked */
done += execute_testcases(fn2);
ck_free(fn2);
continue;
}
free(nl[i]);
if (!S_ISREG(st.st_mode) || !st.st_size) {
ck_free(fn2);
continue;
}
if (st.st_size > MAX_FILE && !be_quiet) {
WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
}
// DO
if (read_file(fn2)) {
if (wait_for_gdb) {
fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
fprintf(stderr, "exec: kill -CONT %d\n", getpid());
kill(0, SIGSTOP);
}
showmap_run_target_forkserver(fsrv, in_data, in_len);
ck_free(in_data);
++done;
if (collect_coverage)
analyze_results(fsrv);
else
tcnt = write_results_to_file(fsrv, outfile);
}
}
free(nl); /* not tracked */
return done;
}
/* Show banner. */
static void show_banner(void) {
@ -1136,15 +1226,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (in_dir) {
DIR * dir_in, *dir_out = NULL;
struct dirent **file_list;
// int done = 0;
u8 infile[PATH_MAX], outfile[PATH_MAX];
u8 wait_for_gdb = 0;
#if !defined(DT_REG)
struct stat statbuf;
#endif
DIR *dir_in, *dir_out = NULL;
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
@ -1245,65 +1327,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
int file_count = scandir(in_dir, &file_list, NULL, alphasort);
if (file_count < 0) {
if (execute_testcases(in_dir) == 0) {
PFATAL("Failed to read from input dir at %s\n", in_dir);
FATAL("could not read input testcases from %s", in_dir);
}
for (int i = 0; i < file_count; i++) {
struct dirent *dir_ent = file_list[i];
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
}
#endif
snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name);
#if !defined(DT_REG) /* use stat() */
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
#endif
if (!collect_coverage)
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
if (read_file(infile)) {
if (wait_for_gdb) {
fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
fprintf(stderr, "exec: kill -CONT %d\n", getpid());
kill(0, SIGSTOP);
}
showmap_run_target_forkserver(fsrv, in_data, in_len);
ck_free(in_data);
if (collect_coverage)
analyze_results(fsrv);
else
tcnt = write_results_to_file(fsrv, outfile);
}
}
free(file_list);
file_list = NULL;
if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
if (dir_out) { closedir(dir_out); }