Skip to content
This repository has been archived by the owner on Apr 30, 2021. It is now read-only.

Commit

Permalink
refactored file read
Browse files Browse the repository at this point in the history
  • Loading branch information
domenukk committed Sep 22, 2020
1 parent 0a6dce1 commit 3aeab46
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 88 deletions.
2 changes: 1 addition & 1 deletion examples/forking-fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ void fuzzer_process_main(llmp_client_t *client, void *data) {
/* Check for engine to be configured properly */
if (afl_engine_check_configuration(engine) != AFL_RET_SUCCESS) { FATAL("Engine configured incompletely"); };
/* Now we can simply load the testcases from the directory given */
AFL_TRY(engine->funcs.load_testcases_from_dir(engine, engine->in_dir, NULL),
AFL_TRY(engine->funcs.load_testcases_from_dir(engine, engine->in_dir),
{ PFATAL("Error loading testcase dir: %s", afl_ret_stringify(err)); });

OKF("Processed %llu input files.", engine->executions);
Expand Down
4 changes: 2 additions & 2 deletions examples/libaflfuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,9 @@ void fuzzer_process_main(llmp_client_t *llmp_client, void *data) {

afl_feedback_cov_t *coverage_feedback = (afl_feedback_cov_t *)(engine->feedbacks[0]);

engine->funcs.load_testcases_from_dir(engine, queue_dirpath, NULL); // ignore if it fails.
engine->funcs.load_testcases_from_dir(engine, queue_dirpath); // ignore if it fails.
/* Now we can simply load the testcases from the directory given */
AFL_TRY(engine->funcs.load_testcases_from_dir(engine, engine->in_dir, NULL),
AFL_TRY(engine->funcs.load_testcases_from_dir(engine, engine->in_dir),
{ PFATAL("Error loading testcase dir: %s", afl_ret_stringify(err)); });

/* The actual fuzzing */
Expand Down
4 changes: 2 additions & 2 deletions include/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct afl_engine_func {

u8 (*execute)(afl_engine_t *, afl_input_t *);
afl_ret_t (*handle_new_message)(afl_engine_t *, llmp_message_t *);
afl_ret_t (*load_testcases_from_dir)(afl_engine_t *, char *, afl_input_t *(*custom_input_init)(void));
afl_ret_t (*load_testcases_from_dir)(afl_engine_t *, char *);
void (*load_zero_testcase)(size_t);

afl_ret_t (*loop)(afl_engine_t *);
Expand Down Expand Up @@ -91,7 +91,7 @@ afl_ret_t afl_engine_add_feedback(afl_engine_t *, afl_feedback_t *);
void afl_set_global_queue(afl_engine_t *engine, afl_queue_global_t *global_queue);

u8 afl_engine_execute(afl_engine_t *, afl_input_t *);
afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *, char *, afl_input_t *(*custom_input_init)());
afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *, char *);
void afl_engine_load_zero_testcase(size_t);
afl_ret_t afl_engine_handle_new_message(afl_engine_t *, llmp_message_t *);

Expand Down
5 changes: 5 additions & 0 deletions include/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,10 @@ void afl_proc_suspend(afl_os_t *);
void afl_proc_resume(afl_os_t *);
afl_exit_t afl_proc_wait(afl_os_t *, bool);

/* Run `handle_file` for each file in the dirpath, recursively.
void *data will be passed to handle_file as 2nd param.
if handle_file returns false, further execution stops. */
afl_ret_t afl_for_each_file(char *dirpath, bool (*handle_file)(char *filename, void *data), void *data);

#endif

113 changes: 31 additions & 82 deletions src/engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,116 +154,65 @@ afl_ret_t afl_engine_add_feedback(afl_engine_t *engine, afl_feedback_t *feedback

}

afl_ret_t __afl_engine_load_testcases_from_dir(afl_engine_t *engine, char *dirpath,
afl_input_t *(*custom_input_new)(void)) {
static bool afl_engine_handle_single_testcase_load(char *infile, void *data) {

DIR * dir_in = NULL;
struct dirent *dir_ent = NULL;
char infile[PATH_MAX];
size_t i;
uint32_t ok = 0;
afl_engine_t *engine = (afl_engine_t *)data;

afl_input_t *input;
if (!(dir_in = opendir(dirpath))) { return AFL_RET_FILE_OPEN_ERROR; }

while ((dir_ent = readdir(dir_in))) {

if (dir_ent->d_name[0] == '.') {

continue; // skip anything that starts with '.'

}

snprintf((char *)infile, sizeof(infile), "%s/%s", dirpath, dir_ent->d_name);
infile[sizeof(infile) - 1] = '\0';

/* TODO: Error handling? */
struct stat st;
if (access(infile, R_OK) != 0 || stat(infile, &st) != 0) continue;
if (S_ISDIR(st.st_mode)) {

if (__afl_engine_load_testcases_from_dir(engine, infile, custom_input_new) == AFL_RET_SUCCESS) ok = 1;
continue;

}

if (!S_ISREG(st.st_mode)) continue;

/* TODO: Not sure if this makes any sense at all? */
if (custom_input_new) {

input = custom_input_new();

} else {

input = afl_input_new();
size_t i;

}
afl_input_t *input = afl_input_new();

if (!input) {
if (!input) {

closedir(dir_in);
if (engine->executor->funcs.destroy_cb) { engine->executor->funcs.destroy_cb(engine->executor); };
DBG("Error allocating input %s", infile);
return true;

return AFL_RET_ALLOC;
}

}
AFL_TRY(input->funcs.load_from_file(input, infile), {

AFL_TRY(input->funcs.load_from_file(input, infile), {
WARNF("Error loading seed %s: %s", infile, afl_ret_stringify(err));
free(input);
return true;

WARNF("Error loading seed %s: %s", infile, afl_ret_stringify(err));
free(input);
continue;
});

});
afl_ret_t run_result = engine->funcs.execute(engine, input);

afl_ret_t run_result = engine->funcs.execute(engine, input);
if (run_result == AFL_RET_SUCCESS) {

if (run_result == AFL_RET_SUCCESS) {
if (engine->verbose) OKF("Loaded seed %s", infile);
return true;

if (engine->verbose) OKF("Loaded seed %s", infile);
ok = 1;
} else {

} else {
WARNF("Error loading seed %s", infile);

WARNF("Error loading seed %s", infile);

}
}

/* We add the corpus to the queue initially for all the feedback queues */
/* We add the corpus to the queue initially for all the feedback queues */

for (i = 0; i < engine->feedbacks_count; ++i) {
for (i = 0; i < engine->feedbacks_count; ++i) {

afl_input_t *copy = input->funcs.copy(input);
if (!copy) { return AFL_RET_ERROR_INPUT_COPY; }
afl_entry_t *entry = afl_entry_new(input);
if (!entry) {

afl_entry_t *entry = afl_entry_new(copy);
engine->feedbacks[i]->queue->base.funcs.insert(&engine->feedbacks[i]->queue->base, entry);
DBG("Error allocating entry.");
return true;

}

if (run_result == AFL_RET_WRITE_TO_CRASH) { SAYF("Crashing input found in initial corpus\n"); }

afl_input_delete(input);
input = NULL;
engine->feedbacks[i]->queue->base.funcs.insert(&engine->feedbacks[i]->queue->base, entry);

}

closedir(dir_in);
if (run_result == AFL_RET_WRITE_TO_CRASH) { SAYF("Crashing input found in initial corpus\n"); }

if (ok)
return AFL_RET_SUCCESS;
else
return AFL_RET_EMPTY;
return true;

}

afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *engine, char *dirpath,
afl_input_t *(*custom_input_new)(void)) {

size_t dir_name_size = strlen(dirpath);
if (dirpath[dir_name_size - 1] == '/') { dirpath[dir_name_size - 1] = 0; }
if (access(dirpath, R_OK | X_OK) != 0) return AFL_RET_FILE_OPEN_ERROR;
afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *engine, char *dirpath) {

/* Since, this'll be the first execution, Let's start up the executor here */
if ((engine->executions == 0) && engine->executor->funcs.init_cb) {
Expand All @@ -276,7 +225,7 @@ afl_ret_t afl_engine_load_testcases_from_dir(afl_engine_t *engine, char *dirpath

}

return __afl_engine_load_testcases_from_dir(engine, dirpath, custom_input_new);
return afl_for_each_file(dirpath, afl_engine_handle_single_testcase_load, (void *)engine);

}

Expand Down
77 changes: 76 additions & 1 deletion src/os.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <signal.h>
#include <assert.h>
#include <types.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <dirent.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "os.h"
#include "engine.h"
Expand Down Expand Up @@ -91,3 +94,75 @@ afl_exit_t afl_proc_wait(afl_os_t *afl_os, bool untraced) {

}

static afl_ret_t __afl_for_each_file(char *dirpath, bool (*handle_file)(char *filename, void *data), void *data) {

DIR * dir_in = NULL;
struct dirent *dir_ent = NULL;
char infile[PATH_MAX];
uint32_t ok = 0;

if (!(dir_in = opendir(dirpath))) { return AFL_RET_FILE_OPEN_ERROR; }

while ((dir_ent = readdir(dir_in))) {

if (dir_ent->d_name[0] == '.') {

continue; // skip anything that starts with '.'

}

snprintf((char *)infile, sizeof(infile), "%s/%s", dirpath, dir_ent->d_name);
infile[sizeof(infile) - 1] = '\0';

/* TODO: Error handling? */
struct stat st;
if (access(infile, R_OK) != 0 || stat(infile, &st) != 0) { continue; }
if (S_ISDIR(st.st_mode)) {

if (__afl_for_each_file(infile, handle_file, data) == AFL_RET_SUCCESS) { ok = 1; }
continue;

}

if (!S_ISREG(st.st_mode)) { continue; }

if (!handle_file(infile, data)) {

DBG("Finishing recursive file read");
break;

} else {

ok = 1;

}

}

closedir(dir_in);

if (ok) {

return AFL_RET_SUCCESS;

} else {

return AFL_RET_EMPTY;

}

}

/* Run `handle_file` for each file in the dirpath, recursively.
void *data will be passed to handle_file as 2nd param.
if handle_file returns false, further execution stops. */
afl_ret_t afl_for_each_file(char *dirpath, bool (*handle_file)(char *filename, void *data), void *data) {

size_t dir_name_size = strlen(dirpath);
if (dirpath[dir_name_size - 1] == '/') { dirpath[dir_name_size - 1] = '\0'; }
if (access(dirpath, R_OK | X_OK) != 0) return AFL_RET_FILE_OPEN_ERROR;

return __afl_for_each_file(dirpath, handle_file, data);

}

0 comments on commit 3aeab46

Please sign in to comment.