Index: third_party/afl/src/afl-showmap.c |
diff --git a/third_party/afl/src/afl-showmap.c b/third_party/afl/src/afl-showmap.c |
index bb96002e12dd4ba2c5bd50557d42258289aa5f30..4b81862a27e2b2752ef1bdaf1169da5427e5aeaa 100644 |
--- a/third_party/afl/src/afl-showmap.c |
+++ b/third_party/afl/src/afl-showmap.c |
@@ -63,7 +63,8 @@ static s32 shm_id; /* ID of the SHM region */ |
static u8 quiet_mode, /* Hide non-essential messages? */ |
edges_only, /* Ignore hit counts? */ |
- cmin_mode; /* Generate output in afl-cmin mode? */ |
+ cmin_mode, /* Generate output in afl-cmin mode? */ |
+ binary_mode; /* Write output as a binary map */ |
static volatile u8 |
stop_soon, /* Ctrl-C pressed? */ |
@@ -73,7 +74,7 @@ static volatile u8 |
/* Classify tuple counts. Instead of mapping to individual bits, as in |
afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ |
-static const u8 count_class_lookup[256] = { |
+static const u8 count_class_human[256] = { |
[0] = 0, |
[1] = 1, |
@@ -87,7 +88,21 @@ static const u8 count_class_lookup[256] = { |
}; |
-static void classify_counts(u8* mem) { |
+static const u8 count_class_binary[256] = { |
+ |
+ [0] = 0, |
+ [1] = 1, |
+ [2] = 2, |
+ [3] = 4, |
+ [4 ... 7] = 8, |
+ [8 ... 15] = 16, |
+ [16 ... 31] = 32, |
+ [32 ... 127] = 64, |
+ [128 ... 255] = 128 |
+ |
+}; |
+ |
+static void classify_counts(u8* mem, const u8* map) { |
u32 i = MAP_SIZE; |
@@ -101,7 +116,7 @@ static void classify_counts(u8* mem) { |
} else { |
while (i--) { |
- *mem = count_class_lookup[*mem]; |
+ *mem = map[*mem]; |
mem++; |
} |
@@ -148,8 +163,8 @@ static void setup_shm(void) { |
static u32 write_results(void) { |
s32 fd; |
- FILE* f; |
u32 i, ret = 0; |
+ |
u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), |
caa = !!getenv("AFL_CMIN_ALLOW_ANY"); |
@@ -171,27 +186,40 @@ static u32 write_results(void) { |
} |
- f = fdopen(fd, "w"); |
- if (!f) PFATAL("fdopen() failed"); |
+ if (binary_mode) { |
- for (i = 0; i < MAP_SIZE; i++) { |
+ for (i = 0; i < MAP_SIZE; i++) |
+ if (trace_bits[i]) ret++; |
+ |
+ ck_write(fd, trace_bits, MAP_SIZE, out_file); |
+ close(fd); |
- if (!trace_bits[i]) continue; |
- ret++; |
+ } else { |
- if (cmin_mode) { |
+ FILE* f = fdopen(fd, "w"); |
- if (child_timed_out) break; |
- if (!caa && child_crashed != cco) break; |
+ if (!f) PFATAL("fdopen() failed"); |
- fprintf(f, "%u%u\n", trace_bits[i], i); |
+ for (i = 0; i < MAP_SIZE; i++) { |
- } else fprintf(f, "%06u:%u\n", i, trace_bits[i]); |
+ if (!trace_bits[i]) continue; |
+ ret++; |
- } |
+ if (cmin_mode) { |
+ |
+ if (child_timed_out) break; |
+ if (!caa && child_crashed != cco) break; |
+ |
+ fprintf(f, "%u%u\n", trace_bits[i], i); |
+ |
+ } else fprintf(f, "%06u:%u\n", i, trace_bits[i]); |
+ |
+ } |
- fclose(f); |
+ fclose(f); |
+ |
+ } |
return ret; |
@@ -293,7 +321,8 @@ static void run_target(char** argv) { |
if (*(u32*)trace_bits == EXEC_FAIL_SIG) |
FATAL("Unable to execute '%s'", argv[0]); |
- classify_counts(trace_bits); |
+ classify_counts(trace_bits, binary_mode ? |
+ count_class_binary : count_class_human); |
if (!quiet_mode) |
SAYF(cRST "-- Program output ends --\n"); |
@@ -585,7 +614,7 @@ int main(int argc, char** argv) { |
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; |
- while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQ")) > 0) |
+ while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQb")) > 0) |
switch (opt) { |
@@ -682,6 +711,14 @@ int main(int argc, char** argv) { |
qemu_mode = 1; |
break; |
+ case 'b': |
+ |
+ /* Secret undocumented mode. Writes output in raw binary format |
+ similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */ |
+ |
+ binary_mode = 1; |
+ break; |
+ |
default: |
usage(argv[0]); |