aboutsummaryrefslogtreecommitdiff
path: root/include/afl-persistent-replay.h
diff options
context:
space:
mode:
authorAlexander Shvedov <60114847+a-shvedov@users.noreply.github.com>2024-05-30 10:43:01 +0300
committerGitHub <noreply@github.com>2024-05-30 10:43:01 +0300
commitf8a5f1cd9ea907654f42fa06ce6b6bfd4b8c1b13 (patch)
tree7aec2a095a30ed609ce96f85ec3c4e0a8b8eb74c /include/afl-persistent-replay.h
parent629edb1e78d791894ce9ee6d53259f95fe1a29af (diff)
parente7d871c8bf64962a658e447b90a1a3b43aaddc28 (diff)
downloadafl++-f8a5f1cd9ea907654f42fa06ce6b6bfd4b8c1b13.tar.gz
Merge branch 'AFLplusplus:stable' into stable
Diffstat (limited to 'include/afl-persistent-replay.h')
-rw-r--r--include/afl-persistent-replay.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/include/afl-persistent-replay.h b/include/afl-persistent-replay.h
new file mode 100644
index 00000000..9e60ff9c
--- /dev/null
+++ b/include/afl-persistent-replay.h
@@ -0,0 +1,131 @@
+#ifndef _HAVE_PERSISTENT_REPLAY_H
+#define _HAVE_PERSISTENT_REPLAY_H
+
+#include <dirent.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef PATH_MAX
+ #define PATH_MAX 4096
+#endif
+
+static unsigned short int is_replay_record;
+static unsigned int replay_record;
+static unsigned int replay_record_cnt;
+static char replay_record_path[PATH_MAX];
+static char *replay_record_dir;
+static struct dirent **record_list;
+
+#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
+static char **record_arg = NULL;
+#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
+
+static int select_files(const struct dirent *dirbuf) {
+
+ char fn[PATH_MAX];
+
+ if (dirbuf->d_name[0] == '.') {
+
+ return 0;
+
+ } else {
+
+ snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record);
+ return !!strstr(dirbuf->d_name, fn);
+
+ }
+
+}
+
+static int compare_files(const struct dirent **da, const struct dirent **db) {
+
+ unsigned int c1 = 0, c2 = 0;
+
+ sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1);
+ sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2);
+
+ return c1 - c2;
+
+}
+
+__attribute__((destructor)) static void __afl_record_replay_destroy(void) {
+
+ for (int i = 0; i < replay_record_cnt; i++) {
+
+ free(record_list[i]);
+
+ }
+
+ free(record_list);
+
+}
+
+__attribute__((constructor)) static void __afl_record_replay_init(
+#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
+ int argc, char **argv
+#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
+) {
+
+#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
+ char **argp;
+#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
+
+ struct stat sb;
+
+ /* caveat: if harness uses @@ and we don't pass it, it will regardless loop
+ * the number of iterations defined for AFL_LOOP (on the same file)*/
+ if (!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))) {
+
+ // printf("[warning] AFL_PERSISTENT_REPLAY not set.\n");
+ return;
+
+ }
+
+ replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY"));
+ replay_record_dir = getenv("AFL_PERSISTENT_DIR");
+
+ if (!(stat(replay_record_dir, &sb) == 0 && S_ISDIR(sb.st_mode))) {
+
+ fprintf(stderr, "[error] Can't find the requested record directory!\n");
+ is_replay_record = 0;
+ return;
+
+ }
+
+ replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./",
+ &record_list, select_files, compare_files);
+
+ if (!replay_record_cnt) {
+
+ fprintf(stderr, "[error] Can't find the requested record!\n");
+ is_replay_record = 0;
+
+ }
+
+#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
+ argp = argv;
+ while (*argp) {
+
+ if (!strcmp(*argp, "@@")) {
+
+ record_arg = argp;
+ *record_arg = replay_record_path;
+ break;
+
+ }
+
+ ++argp;
+
+ }
+
+#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
+
+}
+
+#endif // _HAVE_PERSISTENT_REPLAY_H
+