aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-02-26 09:45:43 +0100
committerGitHub <noreply@github.com>2021-02-26 09:45:43 +0100
commit78d96c4dc86ac20e2a6e244017407ccc037ff13b (patch)
treee277f092c27714f75e0c19f9ac8ab18dbfd1745a
parent7ae7b0f3732cfd9d82cf9403818012d00faa07c3 (diff)
parentee0ca07f3c9f7c5971440f5dca70a2ee6f37584d (diff)
downloadafl++-78d96c4dc86ac20e2a6e244017407ccc037ff13b.tar.gz
Merge pull request #759 from AFLplusplus/dev
push to stable
-rw-r--r--README.md25
-rw-r--r--TODO.md5
-rwxr-xr-xafl-plot11
-rw-r--r--custom_mutators/honggfuzz/common.h0
-rw-r--r--custom_mutators/honggfuzz/honggfuzz.h9
-rw-r--r--custom_mutators/honggfuzz/input.h6
l---------custom_mutators/honggfuzz/libhfcommon1
-rw-r--r--custom_mutators/honggfuzz/libhfcommon/common.h3
l---------custom_mutators/honggfuzz/libhfcommon/log.h (renamed from custom_mutators/honggfuzz/log.h)0
l---------custom_mutators/honggfuzz/libhfcommon/util.h (renamed from custom_mutators/honggfuzz/util.h)0
-rw-r--r--custom_mutators/honggfuzz/mangle.c1174
-rw-r--r--docs/Changelog.md25
-rw-r--r--include/afl-fuzz.h6
-rw-r--r--include/common.h1
-rw-r--r--include/config.h26
-rw-r--r--instrumentation/README.lto.md31
-rw-r--r--instrumentation/afl-compiler-rt.o.c14
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc2
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--qemu_mode/libqasan/dlmalloc.c5
-rw-r--r--src/afl-cc.c17
-rw-r--r--src/afl-common.c137
-rw-r--r--src/afl-fuzz-init.c48
-rw-r--r--src/afl-fuzz-redqueen.c114
-rw-r--r--src/afl-fuzz-run.c2
-rw-r--r--src/afl-fuzz-state.c2
-rw-r--r--src/afl-fuzz-stats.c36
-rw-r--r--src/afl-fuzz.c113
-rwxr-xr-xtest/test-qemu-mode.sh9
29 files changed, 1002 insertions, 822 deletions
diff --git a/README.md b/README.md
index 00095390..119426f6 100644
--- a/README.md
+++ b/README.md
@@ -21,9 +21,16 @@
mutations, more and better instrumentation, custom module support, etc.
If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
- on the website.
+ on the website. To cite our work, look at the [Cite](#cite) section.
+ For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
+ with `AFL_LLVM_CMPLOG=1`.
-## Major changes in afl++ 3.0
+## Major changes in afl++ 3.0 + 3.1
+
+With afl++ 3.1 we introduced the following changes from previous behaviours:
+ * The '+' feature of the '-t' option now means to auto-calculate the timeout
+ with the value given being the maximum timeout. The original meaning of
+ "skipping timeouts instead of abort" is now inherent to the -t option.
With afl++ 3.0 we introduced changes that break some previous afl and afl++
behaviours and defaults:
@@ -754,6 +761,8 @@ campaigns as these are much shorter runnings.
`-M` enables deterministic fuzzing, old queue handling etc. which is good for
a fuzzing campaign but not good for short CI runs.
+How this can look like can e.g. be seen at afl++'s setup in Google's [oss-fuzz](https://github.com/google/oss-fuzz/blob/4bb61df7905c6005000f5766e966e6fe30ab4559/infra/base-images/base-builder/compile_afl#L69).
+
## Fuzzing binary-only targets
When source code is *NOT* available, afl++ offers various support for fast,
@@ -1166,8 +1175,18 @@ Thank you!
## Cite
+If you use AFLpluplus to compare to your work, please use either `afl-clang-lto`
+or `afl-clang-fast` with `AFL_LLVM_CMPLOG=1` for building targets and
+`afl-fuzz` with the command line option `-l 2` for fuzzing.
+The most effective setup is the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
+
If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20:
-```
+
++ Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
+
+Bibtex:
+
+```bibtex
@inproceedings {AFLplusplus-Woot20,
author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse},
title = {{AFL++}: Combining Incremental Steps of Fuzzing Research},
diff --git a/TODO.md b/TODO.md
index 890a481a..4615c456 100644
--- a/TODO.md
+++ b/TODO.md
@@ -6,16 +6,13 @@
- CPU affinity for many cores? There seems to be an issue > 96 cores
- afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin()
+ - afl_custom_splice()
- intel-pt tracer
## Further down the road
afl-fuzz:
- setting min_len/max_len/start_offset/end_offset limits for mutation output
- - add __sanitizer_cov_trace_cmp* support via shmem
-
-llvm_mode:
- - add __sanitizer_cov_trace_cmp* support
qemu_mode:
- non colliding instrumentation
diff --git a/afl-plot b/afl-plot
index 0faed0ec..ba100d3e 100755
--- a/afl-plot
+++ b/afl-plot
@@ -99,7 +99,7 @@ if [ ! -d "$outputdir" ]; then
fi
-rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png"
+rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png"
mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null
echo "[*] Generating plots..."
@@ -152,6 +152,12 @@ set ytics auto
plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
'$inputdir/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
+set terminal png truecolor enhanced size 1000,300 butt
+set output '$outputdir/edges.png'
+
+set ytics auto
+plot '$inputdir/plot_data' using 1:13 with lines title ' edges' linecolor rgb '#0090ff' linewidth 3
+
_EOF_
) | gnuplot
@@ -172,6 +178,7 @@ cat >"$outputdir/index.html" <<_EOF_
<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
</table>
<p>
+<img src="edges.png" width=1000 height=300>
<img src="high_freq.png" width=1000 height=300><p>
<img src="low_freq.png" width=1000 height=200><p>
<img src="exec_speed.png" width=1000 height=200>
@@ -183,7 +190,7 @@ _EOF_
# sensitive, this seems like a reasonable trade-off.
chmod 755 "$outputdir"
-chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/index.html"
+chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html"
echo "[+] All done - enjoy your charts!"
diff --git a/custom_mutators/honggfuzz/common.h b/custom_mutators/honggfuzz/common.h
deleted file mode 100644
index e69de29b..00000000
--- a/custom_mutators/honggfuzz/common.h
+++ /dev/null
diff --git a/custom_mutators/honggfuzz/honggfuzz.h b/custom_mutators/honggfuzz/honggfuzz.h
index 9d07fdf4..c80cdd87 100644
--- a/custom_mutators/honggfuzz/honggfuzz.h
+++ b/custom_mutators/honggfuzz/honggfuzz.h
@@ -39,7 +39,7 @@
#include "libhfcommon/util.h"
#define PROG_NAME "honggfuzz"
-#define PROG_VERSION "2.3"
+#define PROG_VERSION "2.4"
/* Name of the template which will be replaced with the proper name of the file */
#define _HF_FILE_PLACEHOLDER "___FILE___"
@@ -208,6 +208,7 @@ typedef struct {
const char* crashDir;
const char* covDirNew;
bool saveUnique;
+ bool saveSmaller;
size_t dynfileqMaxSz;
size_t dynfileqCnt;
dynfile_t* dynfileqCurrent;
@@ -279,9 +280,9 @@ typedef struct {
cmpfeedback_t* cmpFeedbackMap;
int cmpFeedbackFd;
bool cmpFeedback;
- const char* blacklistFile;
- uint64_t* blacklist;
- size_t blacklistCnt;
+ const char* blocklistFile;
+ uint64_t* blocklist;
+ size_t blocklistCnt;
bool skipFeedbackOnTimeout;
uint64_t maxCov[4];
dynFileMethod_t dynFileMethod;
diff --git a/custom_mutators/honggfuzz/input.h b/custom_mutators/honggfuzz/input.h
index 7b0c55ae..09712f54 100644
--- a/custom_mutators/honggfuzz/input.h
+++ b/custom_mutators/honggfuzz/input.h
@@ -77,11 +77,11 @@ static inline uint64_t util_rndGet(uint64_t min, uint64_t max) {
}
static inline uint64_t util_rnd64() { return rand_below(afl_struct, 1 << 30); }
-static inline size_t input_getRandomInputAsBuf(run_t *run, const uint8_t **buf) {
- *buf = queue_input;
+static inline const uint8_t* input_getRandomInputAsBuf(run_t* run, size_t* len) {
+ *len = queue_input_size;
run->dynfile->data = queue_input;
run->dynfile->size = queue_input_size;
- return queue_input_size;
+ return queue_input;
}
static inline void input_setSize(run_t* run, size_t sz) {
run->dynfile->size = sz;
diff --git a/custom_mutators/honggfuzz/libhfcommon b/custom_mutators/honggfuzz/libhfcommon
deleted file mode 120000
index 945c9b46..00000000
--- a/custom_mutators/honggfuzz/libhfcommon
+++ /dev/null
@@ -1 +0,0 @@
-. \ No newline at end of file
diff --git a/custom_mutators/honggfuzz/libhfcommon/common.h b/custom_mutators/honggfuzz/libhfcommon/common.h
new file mode 100644
index 00000000..c8cf1329
--- /dev/null
+++ b/custom_mutators/honggfuzz/libhfcommon/common.h
@@ -0,0 +1,3 @@
+#ifndef LOG_E
+ #define LOG_E LOG_F
+#endif
diff --git a/custom_mutators/honggfuzz/log.h b/custom_mutators/honggfuzz/libhfcommon/log.h
index 51e19654..51e19654 120000
--- a/custom_mutators/honggfuzz/log.h
+++ b/custom_mutators/honggfuzz/libhfcommon/log.h
diff --git a/custom_mutators/honggfuzz/util.h b/custom_mutators/honggfuzz/libhfcommon/util.h
index 51e19654..51e19654 120000
--- a/custom_mutators/honggfuzz/util.h
+++ b/custom_mutators/honggfuzz/libhfcommon/util.h
diff --git a/custom_mutators/honggfuzz/mangle.c b/custom_mutators/honggfuzz/mangle.c
index 9c3d1ed4..637d428d 100644
--- a/custom_mutators/honggfuzz/mangle.c
+++ b/custom_mutators/honggfuzz/mangle.c
@@ -39,252 +39,208 @@
#include "libhfcommon/log.h"
#include "libhfcommon/util.h"
-static inline size_t mangle_LenLeft(run_t *run, size_t off) {
-
- if (off >= run->dynfile->size) {
-
- LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
-
- }
-
- return (run->dynfile->size - off - 1);
-
+static inline size_t mangle_LenLeft(run_t* run, size_t off) {
+ if (off >= run->dynfile->size) {
+ LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
+ }
+ return (run->dynfile->size - off - 1);
}
-/* Get a random value <1:max>, but prefer smaller ones - up to 4KiB */
+/*
+ * Get a random value <1:max>, but prefer smaller ones
+ * Based on an idea by https://twitter.com/gamozolabs
+ */
static inline size_t mangle_getLen(size_t max) {
+ if (max > _HF_INPUT_MAX_SIZE) {
+ LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE);
+ }
+ if (max == 0) {
+ LOG_F("max == 0");
+ }
+ if (max == 1) {
+ return 1;
+ }
- if (max > _HF_INPUT_MAX_SIZE) {
-
- LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max,
- (size_t)_HF_INPUT_MAX_SIZE);
-
- }
-
- if (max == 0) { LOG_F("max == 0"); }
- if (max == 1) { return 1; }
-
- /* Give 50% chance the the uniform distribution */
- switch (util_rndGet(0, 9)) {
-
- case 0:
- return (size_t)util_rndGet(1, HF_MIN(16, max));
- case 1:
- return (size_t)util_rndGet(1, HF_MIN(64, max));
- case 2:
- return (size_t)util_rndGet(1, HF_MIN(256, max));
- case 3:
- return (size_t)util_rndGet(1, HF_MIN(1024, max));
- case 4:
- return (size_t)util_rndGet(1, HF_MIN(4096, max));
- default:
- break;
-
- }
-
- return (size_t)util_rndGet(1, max);
+ /* Give 50% chance the the uniform distribution */
+ if (util_rnd64() & 1) {
+ return (size_t)util_rndGet(1, max);
+ }
+ /* effectively exprand() */
+ return (size_t)util_rndGet(1, util_rndGet(1, max));
}
/* Prefer smaller values here, so use mangle_getLen() */
-static inline size_t mangle_getOffSet(run_t *run) {
-
- return mangle_getLen(run->dynfile->size) - 1;
-
+static inline size_t mangle_getOffSet(run_t* run) {
+ return mangle_getLen(run->dynfile->size) - 1;
}
/* Offset which can be equal to the file size */
-static inline size_t mangle_getOffSetPlus1(run_t *run) {
-
- size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
- return mangle_getLen(reqlen) - 1;
-
+static inline size_t mangle_getOffSetPlus1(run_t* run) {
+ size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
+ return mangle_getLen(reqlen) - 1;
}
-static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to,
- size_t len) {
-
- if (off_from >= run->dynfile->size) { return; }
- if (off_to >= run->dynfile->size) { return; }
- if (off_from == off_to) { return; }
-
- size_t len_from = run->dynfile->size - off_from;
- len = HF_MIN(len, len_from);
+static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) {
+ if (off_from >= run->dynfile->size) {
+ return;
+ }
+ if (off_to >= run->dynfile->size) {
+ return;
+ }
+ if (off_from == off_to) {
+ return;
+ }
- size_t len_to = run->dynfile->size - off_to;
- len = HF_MIN(len, len_to);
+ size_t len_from = run->dynfile->size - off_from;
+ len = HF_MIN(len, len_from);
- memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
+ size_t len_to = run->dynfile->size - off_to;
+ len = HF_MIN(len, len_to);
+ memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
}
-static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src,
- size_t len, bool printable) {
-
- if (len == 0) { return; }
- size_t maxToCopy = run->dynfile->size - off;
- if (len > maxToCopy) { len = maxToCopy; }
-
- memmove(&run->dynfile->data[off], src, len);
- if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); }
+static inline void mangle_Overwrite(
+ run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) {
+ if (len == 0) {
+ return;
+ }
+ size_t maxToCopy = run->dynfile->size - off;
+ if (len > maxToCopy) {
+ len = maxToCopy;
+ }
+ memmove(&run->dynfile->data[off], src, len);
+ if (printable) {
+ util_turnToPrintable(&run->dynfile->data[off], len);
+ }
}
-static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len,
- bool printable) {
-
- if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; }
- if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
-
- len = run->global->mutate.maxInputSz - run->dynfile->size;
-
- }
-
- input_setSize(run, run->dynfile->size + len);
- mangle_Move(run, off, off + len, run->dynfile->size);
- if (printable) { memset(&run->dynfile->data[off], ' ', len); }
+static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) {
+ if (run->dynfile->size >= run->global->mutate.maxInputSz) {
+ return 0;
+ }
+ if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
+ len = run->global->mutate.maxInputSz - run->dynfile->size;
+ }
- return len;
+ input_setSize(run, run->dynfile->size + len);
+ mangle_Move(run, off, off + len, run->dynfile->size);
+ if (printable) {
+ memset(&run->dynfile->data[off], ' ', len);
+ }
+ return len;
}
-static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val,
- size_t len, bool printable) {
-
- len = mangle_Inflate(run, off, len, printable);
- mangle_Overwrite(run, off, val, len, printable);
-
+static inline void mangle_Insert(
+ run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
+ len = mangle_Inflate(run, off, len, printable);
+ mangle_Overwrite(run, off, val, len, printable);
}
-static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len,
- bool printable) {
-
- if (util_rnd64() % 2) {
-
- mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
-
- } else {
-
- mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
-
- }
-
+static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) {
+ if (util_rnd64() & 1) {
+ mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
+ } else {
+ mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
+ }
}
-static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) {
-
- size_t off1 = mangle_getOffSet(run);
- size_t maxlen1 = run->dynfile->size - off1;
-
- size_t off2 = mangle_getOffSet(run);
- size_t maxlen2 = run->dynfile->size - off2;
-
- size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
- uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
- defer {
-
- free(tmpbuf);
-
- };
-
- memcpy(tmpbuf, &run->dynfile->data[off1], len);
- memmove(&run->dynfile->data[off1], &run->dynfile->data[off2], len);
- memcpy(&run->dynfile->data[off2], tmpbuf, len);
-
+static inline void mangle_UseValueAt(
+ run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
+ if (util_rnd64() & 1) {
+ mangle_Overwrite(run, off, val, len, printable);
+ } else {
+ mangle_Insert(run, off, val, len, printable);
+ }
}
-static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) {
-
- size_t off = mangle_getOffSet(run);
- size_t len = mangle_getLen(run->dynfile->size - off);
-
- /* Use a temp buf, as Insert/Inflate can change source bytes */
- uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
- defer {
+static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) {
+ /* No big deal if those two are overlapping */
+ size_t off1 = mangle_getOffSet(run);
+ size_t maxlen1 = run->dynfile->size - off1;
+ size_t off2 = mangle_getOffSet(run);
+ size_t maxlen2 = run->dynfile->size - off2;
+ size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
- free(tmpbuf);
-
- };
-
- memcpy(tmpbuf, &run->dynfile->data[off], len);
-
- mangle_UseValue(run, tmpbuf, len, printable);
+ if (off1 == off2) {
+ return;
+ }
+ for (size_t i = 0; i < (len / 2); i++) {
+ /*
+ * First - from the head, next from the tail. Don't worry about layout of the overlapping
+ * part - there's no good solution to that, and it can be left somewhat scrambled,
+ * while still preserving the entropy
+ */
+ const uint8_t tmp1 = run->dynfile->data[off2 + i];
+ run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
+ run->dynfile->data[off1 + i] = tmp1;
+ const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
+ run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i];
+ run->dynfile->data[off1 + (len - 1) - i] = tmp2;
+ }
}
-static void mangle_Bytes(run_t *run, bool printable) {
-
- uint16_t buf;
- if (printable) {
-
- util_rndBufPrintable((uint8_t *)&buf, sizeof(buf));
-
- } else {
+static void mangle_MemCopy(run_t* run, bool printable HF_ATTR_UNUSED) {
+ size_t off = mangle_getOffSet(run);
+ size_t len = mangle_getLen(run->dynfile->size - off);
- buf = util_rnd64();
-
- }
-
- /* Overwrite with random 1-2-byte values */
- size_t toCopy = util_rndGet(1, 2);
- mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable);
+ /* Use a temp buf, as Insert/Inflate can change source bytes */
+ uint8_t* tmpbuf = (uint8_t*)util_Malloc(len);
+ defer {
+ free(tmpbuf);
+ };
+ memmove(tmpbuf, &run->dynfile->data[off], len);
+ mangle_UseValue(run, tmpbuf, len, printable);
}
-static void mangle_ByteRepeatOverwrite(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t destOff = off + 1;
- size_t maxSz = run->dynfile->size - destOff;
-
- /* No space to repeat */
- if (!maxSz) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- size_t len = mangle_getLen(maxSz);
- memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
+static void mangle_Bytes(run_t* run, bool printable) {
+ uint16_t buf;
+ if (printable) {
+ util_rndBufPrintable((uint8_t*)&buf, sizeof(buf));
+ } else {
+ buf = util_rnd64();
+ }
+ /* Overwrite with random 1-2-byte values */
+ size_t toCopy = util_rndGet(1, 2);
+ mangle_UseValue(run, (const uint8_t*)&buf, toCopy, printable);
}
-static void mangle_ByteRepeatInsert(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t destOff = off + 1;
- size_t maxSz = run->dynfile->size - destOff;
+static void mangle_ByteRepeat(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ size_t destOff = off + 1;
+ size_t maxSz = run->dynfile->size - destOff;
- /* No space to repeat */
- if (!maxSz) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- size_t len = mangle_getLen(maxSz);
- len = mangle_Inflate(run, destOff, len, printable);
- memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
+ /* No space to repeat */
+ if (!maxSz) {
+ mangle_Bytes(run, printable);
+ return;
+ }
+ size_t len = mangle_getLen(maxSz);
+ if (util_rnd64() & 0x1) {
+ len = mangle_Inflate(run, destOff, len, printable);
+ }
+ memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
}
-static void mangle_Bit(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
- if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); }
-
+static void mangle_Bit(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
+ if (printable) {
+ util_turnToPrintable(&(run->dynfile->data[off]), 1);
+ }
}
static const struct {
-
- const uint8_t val[8];
- const size_t size;
-
+ const uint8_t val[8];
+ const size_t size;
} mangleMagicVals[] = {
-
/* 1B - No endianness */
{"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
{"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
@@ -516,522 +472,436 @@ static const struct {
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
{"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
{"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
-
};
-static void mangle_Magic(run_t *run, bool printable) {
-
- uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
- mangle_UseValue(run, mangleMagicVals[choice].val,
- mangleMagicVals[choice].size, printable);
-
-}
-
-static void mangle_StaticDict(run_t *run, bool printable) {
-
- if (run->global->mutate.dictionaryCnt == 0) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
- mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
- run->global->mutate.dictionary[choice].len, printable);
-
+static void mangle_Magic(run_t* run, bool printable) {
+ uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
+ mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable);
}
-static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) {
-
- if (!run->global->feedback.cmpFeedback) { return NULL; }
- cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap;
- uint32_t cnt = ATOMIC_GET(cmpf->cnt);
- if (cnt == 0) { return NULL; }
- if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); }
- uint32_t choice = util_rndGet(0, cnt - 1);
- *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
- if (*len == 0) { return NULL; }
- return cmpf->valArr[choice].val;
-
+static void mangle_StaticDict(run_t* run, bool printable) {
+ if (run->global->mutate.dictionaryCnt == 0) {
+ mangle_Bytes(run, printable);
+ return;
+ }
+ uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
+ mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
+ run->global->mutate.dictionary[choice].len, printable);
}
-static void mangle_ConstFeedbackDict(run_t *run, bool printable) {
-
- size_t len;
- const uint8_t *val = mangle_FeedbackDict(run, &len);
- if (val == NULL) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- mangle_UseValue(run, val, len, printable);
-
+static inline const uint8_t* mangle_FeedbackDict(run_t* run, size_t* len) {
+ if (!run->global->feedback.cmpFeedback) {
+ return NULL;
+ }
+ cmpfeedback_t* cmpf = run->global->feedback.cmpFeedbackMap;
+ uint32_t cnt = ATOMIC_GET(cmpf->cnt);
+ if (cnt == 0) {
+ return NULL;
+ }
+ if (cnt > ARRAYSIZE(cmpf->valArr)) {
+ cnt = ARRAYSIZE(cmpf->valArr);
+ }
+ uint32_t choice = util_rndGet(0, cnt - 1);
+ *len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
+ if (*len == 0) {
+ return NULL;
+ }
+ return cmpf->valArr[choice].val;
}
-static void mangle_MemSet(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t len = mangle_getLen(run->dynfile->size - off);
- int val =
- printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
-
- memset(&run->dynfile->data[off], val, len);
-
+static void mangle_ConstFeedbackDict(run_t* run, bool printable) {
+ size_t len;
+ const uint8_t* val = mangle_FeedbackDict(run, &len);
+ if (val == NULL) {
+ mangle_Bytes(run, printable);
+ return;
+ }
+ mangle_UseValue(run, val, len, printable);
}
-static void mangle_RandomOverwrite(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t len = mangle_getLen(run->dynfile->size - off);
- if (printable) {
-
- util_rndBufPrintable(&run->dynfile->data[off], len);
-
- } else {
-
- util_rndBuf(&run->dynfile->data[off], len);
+static void mangle_MemSet(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ size_t len = mangle_getLen(run->dynfile->size - off);
+ int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
- }
+ if (util_rnd64() & 1) {
+ len = mangle_Inflate(run, off, len, printable);
+ }
+ memset(&run->dynfile->data[off], val, len);
}
-static void mangle_RandomInsert(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t len = mangle_getLen(run->dynfile->size - off);
-
- len = mangle_Inflate(run, off, len, printable);
-
- if (printable) {
+static void mangle_MemClr(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ size_t len = mangle_getLen(run->dynfile->size - off);
+ int val = printable ? ' ' : 0;
- util_rndBufPrintable(&run->dynfile->data[off], len);
-
- } else {
-
- util_rndBuf(&run->dynfile->data[off], len);
-
- }
+ if (util_rnd64() & 1) {
+ len = mangle_Inflate(run, off, len, printable);
+ }
+ memset(&run->dynfile->data[off], val, len);
}
-static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen,
- uint64_t range, bool printable) {
-
- int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
-
- switch (varLen) {
-
- case 1: {
-
- run->dynfile->data[off] += delta;
- break;
+static void mangle_RandomBuf(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ size_t len = mangle_getLen(run->dynfile->size - off);
+ if (util_rnd64() & 1) {
+ len = mangle_Inflate(run, off, len, printable);
}
- case 2: {
-
- int16_t val;
- memcpy(&val, &run->dynfile->data[off], sizeof(val));
- if (util_rnd64() & 0x1) {
-
- val += delta;
-
- } else {
-
- /* Foreign endianess */
- val = __builtin_bswap16(val);
- val += delta;
- val = __builtin_bswap16(val);
-
- }
-
- mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
- break;
-
+ if (printable) {
+ util_rndBufPrintable(&run->dynfile->data[off], len);
+ } else {
+ util_rndBuf(&run->dynfile->data[off], len);
}
+}
- case 4: {
-
- int32_t val;
- memcpy(&val, &run->dynfile->data[off], sizeof(val));
- if (util_rnd64() & 0x1) {
-
- val += delta;
-
- } else {
-
- /* Foreign endianess */
- val = __builtin_bswap32(val);
- val += delta;
- val = __builtin_bswap32(val);
-
- }
-
- mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
- break;
-
+static inline void mangle_AddSubWithRange(
+ run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) {
+ int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
+
+ switch (varLen) {
+ case 1: {
+ run->dynfile->data[off] += delta;
+ break;
+ }
+ case 2: {
+ int16_t val;
+ memcpy(&val, &run->dynfile->data[off], sizeof(val));
+ if (util_rnd64() & 0x1) {
+ val += delta;
+ } else {
+ /* Foreign endianess */
+ val = __builtin_bswap16(val);
+ val += delta;
+ val = __builtin_bswap16(val);
+ }
+ mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
+ break;
+ }
+ case 4: {
+ int32_t val;
+ memcpy(&val, &run->dynfile->data[off], sizeof(val));
+ if (util_rnd64() & 0x1) {
+ val += delta;
+ } else {
+ /* Foreign endianess */
+ val = __builtin_bswap32(val);
+ val += delta;
+ val = __builtin_bswap32(val);
+ }
+ mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
+ break;
+ }
+ case 8: {
+ int64_t val;
+ memcpy(&val, &run->dynfile->data[off], sizeof(val));
+ if (util_rnd64() & 0x1) {
+ val += delta;
+ } else {
+ /* Foreign endianess */
+ val = __builtin_bswap64(val);
+ val += delta;
+ val = __builtin_bswap64(val);
+ }
+ mangle_Overwrite(run, off, (uint8_t*)&val, varLen, printable);
+ break;
+ }
+ default: {
+ LOG_F("Unknown variable length size: %zu", varLen);
+ }
}
+}
- case 8: {
-
- int64_t val;
- memcpy(&val, &run->dynfile->data[off], sizeof(val));
- if (util_rnd64() & 0x1) {
-
- val += delta;
-
- } else {
-
- /* Foreign endianess */
- val = __builtin_bswap64(val);
- val += delta;
- val = __builtin_bswap64(val);
-
- }
-
- mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
- break;
+static void mangle_AddSub(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ /* 1,2,4,8 */
+ size_t varLen = 1U << util_rndGet(0, 3);
+ if ((run->dynfile->size - off) < varLen) {
+ varLen = 1;
}
- default: {
-
- LOG_F("Unknown variable length size: %zu", varLen);
-
+ uint64_t range;
+ switch (varLen) {
+ case 1:
+ range = 16;
+ break;
+ case 2:
+ range = 4096;
+ break;
+ case 4:
+ range = 1048576;
+ break;
+ case 8:
+ range = 268435456;
+ break;
+ default:
+ LOG_F("Invalid operand size: %zu", varLen);
}
- }
-
-}
-
-static void mangle_AddSub(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
-
- /* 1,2,4,8 */
- size_t varLen = 1U << util_rndGet(0, 3);
- if ((run->dynfile->size - off) < varLen) { varLen = 1; }
-
- uint64_t range;
- switch (varLen) {
-
- case 1:
- range = 16;
- break;
- case 2:
- range = 4096;
- break;
- case 4:
- range = 1048576;
- break;
- case 8:
- range = 268435456;
- break;
- default:
- LOG_F("Invalid operand size: %zu", varLen);
-
- }
-
- mangle_AddSubWithRange(run, off, varLen, range, printable);
-
-}
-
-static void mangle_IncByte(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- if (printable) {
-
- run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
-
- } else {
-
- run->dynfile->data[off] += (uint8_t)1UL;
-
- }
-
+ mangle_AddSubWithRange(run, off, varLen, range, printable);
}
-static void mangle_DecByte(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- if (printable) {
-
- run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
-
- } else {
-
- run->dynfile->data[off] -= (uint8_t)1UL;
-
- }
-
-}
-
-static void mangle_NegByte(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- if (printable) {
-
- run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
-
- } else {
-
- run->dynfile->data[off] = ~(run->dynfile->data[off]);
-
- }
-
+static void mangle_IncByte(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ if (printable) {
+ run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
+ } else {
+ run->dynfile->data[off] += (uint8_t)1UL;
+ }
}
-static void mangle_Expand(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
- size_t len;
- if (util_rnd64() % 16) {
-
- len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
-
- } else {
-
- len = mangle_getLen(run->global->mutate.maxInputSz - off);
-
- }
-
- mangle_Inflate(run, off, len, printable);
-
+static void mangle_DecByte(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ if (printable) {
+ run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
+ } else {
+ run->dynfile->data[off] -= (uint8_t)1UL;
+ }
}
-static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) {
-
- if (run->dynfile->size <= 2U) { return; }
-
- size_t off_start = mangle_getOffSet(run);
- size_t len = mangle_LenLeft(run, off_start);
- if (len == 0) { return; }
- if (util_rnd64() % 16) {
-
- len = mangle_getLen(HF_MIN(16, len));
-
- } else {
-
- len = mangle_getLen(len);
-
- }
-
- size_t off_end = off_start + len;
- size_t len_to_move = run->dynfile->size - off_end;
-
- mangle_Move(run, off_end, off_start, len_to_move);
- input_setSize(run, run->dynfile->size - len);
-
+static void mangle_NegByte(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ if (printable) {
+ run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
+ } else {
+ run->dynfile->data[off] = ~(run->dynfile->data[off]);
+ }
}
-static void mangle_ASCIINum(run_t *run, bool printable) {
-
- size_t len = util_rndGet(2, 8);
-
- char buf[20];
- snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
-
- mangle_UseValue(run, (const uint8_t *)buf, len, printable);
+static void mangle_Expand(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
+ size_t len;
+ if (util_rnd64() % 16) {
+ len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
+ } else {
+ len = mangle_getLen(run->global->mutate.maxInputSz - off);
+ }
+ mangle_Inflate(run, off, len, printable);
}
-static void mangle_ASCIINumChange(run_t *run, bool printable) {
-
- size_t off = mangle_getOffSet(run);
-
- /* Find a digit */
- for (; off < run->dynfile->size; off++) {
-
- if (isdigit(run->dynfile->data[off])) { break; }
-
- }
-
- if (off == run->dynfile->size) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- size_t len = HF_MIN(20, run->dynfile->size - off);
- char numbuf[21] = {};
- strncpy(numbuf, (const char *)&run->dynfile->data[off], len);
- uint64_t val = (uint64_t)strtoull(numbuf, NULL, 10);
-
- switch (util_rndGet(0, 5)) {
-
- case 0:
- val += util_rndGet(1, 256);
- break;
- case 1:
- val -= util_rndGet(1, 256);
- break;
- case 2:
- val *= util_rndGet(1, 256);
- break;
- case 3:
- val /= util_rndGet(1, 256);
- break;
- case 4:
- val = ~(val);
- break;
- case 5:
- val = util_rnd64();
- break;
- default:
- LOG_F("Invalid choice");
-
- };
+static void mangle_Shrink(run_t* run, bool printable HF_ATTR_UNUSED) {
+ if (run->dynfile->size <= 2U) {
+ return;
+ }
- len = HF_MIN((size_t)snprintf(numbuf, sizeof(numbuf), "%" PRIu64, val), len);
- mangle_Overwrite(run, off, (const uint8_t *)numbuf, len, printable);
+ size_t off_start = mangle_getOffSet(run);
+ size_t len = mangle_LenLeft(run, off_start);
+ if (len == 0) {
+ return;
+ }
+ if (util_rnd64() % 16) {
+ len = mangle_getLen(HF_MIN(16, len));
+ } else {
+ len = mangle_getLen(len);
+ }
+ size_t off_end = off_start + len;
+ size_t len_to_move = run->dynfile->size - off_end;
+ mangle_Move(run, off_end, off_start, len_to_move);
+ input_setSize(run, run->dynfile->size - len);
}
+static void mangle_ASCIINum(run_t* run, bool printable) {
+ size_t len = util_rndGet(2, 8);
-static void mangle_Splice(run_t *run, bool printable) {
-
- const uint8_t *buf;
- size_t sz = input_getRandomInputAsBuf(run, &buf);
- if (!sz) {
-
- mangle_Bytes(run, printable);
- return;
-
- }
-
- size_t remoteOff = mangle_getLen(sz) - 1;
- size_t len = mangle_getLen(sz - remoteOff);
- mangle_UseValue(run, &buf[remoteOff], len, printable);
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
+ mangle_UseValue(run, (const uint8_t*)buf, len, printable);
}
-static void mangle_Resize(run_t *run, bool printable) {
-
- ssize_t oldsz = run->dynfile->size;
- ssize_t newsz = 0;
-
- uint64_t choice = util_rndGet(0, 32);
- switch (choice) {
+static void mangle_ASCIINumChange(run_t* run, bool printable) {
+ size_t off = mangle_getOffSet(run);
- case 0: /* Set new size arbitrarily */
- newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
- break;
- case 1 ... 4: /* Increase size by a small value */
- newsz = oldsz + (ssize_t)util_rndGet(0, 8);
- break;
- case 5: /* Increase size by a larger value */
- newsz = oldsz + (ssize_t)util_rndGet(9, 128);
- break;
- case 6 ... 9: /* Decrease size by a small value */
- newsz = oldsz - (ssize_t)util_rndGet(0, 8);
- break;
- case 10: /* Decrease size by a larger value */
- newsz = oldsz - (ssize_t)util_rndGet(9, 128);
- break;
- case 11 ... 32: /* Do nothing */
- newsz = oldsz;
- break;
- default:
- LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
- break;
-
- }
-
- if (newsz < 1) { newsz = 1; }
- if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
-
- newsz = run->global->mutate.maxInputSz;
+ /* Find a digit */
+ for (; off < run->dynfile->size; off++) {
+ if (isdigit(run->dynfile->data[off])) {
+ break;
+ }
+ }
+ size_t left = run->dynfile->size - off;
+ if (left == 0) {
+ return;
+ }
- }
+ size_t len = 0;
+ uint64_t val = 0;
+ /* 20 is maximum lenght of a string representing a 64-bit unsigned value */
+ for (len = 0; (len < 20) && (len < left); len++) {
+ char c = run->dynfile->data[off + len];
+ if (!isdigit(c)) {
+ break;
+ }
+ val *= 10;
+ val += (c - '0');
+ }
- input_setSize(run, (size_t)newsz);
- if (newsz > oldsz) {
+ switch (util_rndGet(0, 7)) {
+ case 0:
+ val++;
+ break;
+ case 1:
+ val--;
+ break;
+ case 2:
+ val *= 2;
+ break;
+ case 3:
+ val /= 2;
+ break;
+ case 4:
+ val = util_rnd64();
+ break;
+ case 5:
+ val += util_rndGet(1, 256);
+ break;
+ case 6:
+ val -= util_rndGet(1, 256);
+ break;
+ case 7:
+ val = ~(val);
+ break;
+ default:
+ LOG_F("Invalid choice");
+ };
+
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
+
+ mangle_UseValueAt(run, off, (const uint8_t*)buf, len, printable);
+}
+
+static void mangle_Splice(run_t* run, bool printable) {
+ if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
+ mangle_Bytes(run, printable);
+ return;
+ }
- if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); }
+ size_t sz = 0;
+ const uint8_t* buf = input_getRandomInputAsBuf(run, &sz);
+ if (!buf) {
+ LOG_E("input_getRandomInputAsBuf() returned no input");
+ mangle_Bytes(run, printable);
+ return;
+ }
+ if (!sz) {
+ mangle_Bytes(run, printable);
+ return;
+ }
- }
+ size_t remoteOff = mangle_getLen(sz) - 1;
+ size_t len = mangle_getLen(sz - remoteOff);
+ mangle_UseValue(run, &buf[remoteOff], len, printable);
+}
+
+static void mangle_Resize(run_t* run, bool printable) {
+ ssize_t oldsz = run->dynfile->size;
+ ssize_t newsz = 0;
+
+ uint64_t choice = util_rndGet(0, 32);
+ switch (choice) {
+ case 0: /* Set new size arbitrarily */
+ newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
+ break;
+ case 1 ... 4: /* Increase size by a small value */
+ newsz = oldsz + (ssize_t)util_rndGet(0, 8);
+ break;
+ case 5: /* Increase size by a larger value */
+ newsz = oldsz + (ssize_t)util_rndGet(9, 128);
+ break;
+ case 6 ... 9: /* Decrease size by a small value */
+ newsz = oldsz - (ssize_t)util_rndGet(0, 8);
+ break;
+ case 10: /* Decrease size by a larger value */
+ newsz = oldsz - (ssize_t)util_rndGet(9, 128);
+ break;
+ case 11 ... 32: /* Do nothing */
+ newsz = oldsz;
+ break;
+ default:
+ LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
+ break;
+ }
+ if (newsz < 1) {
+ newsz = 1;
+ }
+ if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
+ newsz = run->global->mutate.maxInputSz;
+ }
+ input_setSize(run, (size_t)newsz);
+ if (newsz > oldsz) {
+ if (printable) {
+ memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz);
+ }
+ }
}
-void mangle_mangleContent(run_t *run, int speed_factor) {
-
- static void (*const mangleFuncs[])(run_t * run, bool printable) = {
-
- /* Every *Insert or Expand expands file, so add more Shrink's */
- mangle_Shrink,
- mangle_Shrink,
- mangle_Shrink,
- mangle_Shrink,
- mangle_Expand,
- mangle_Bit,
- mangle_IncByte,
- mangle_DecByte,
- mangle_NegByte,
- mangle_AddSub,
- mangle_MemSet,
- mangle_MemSwap,
- mangle_MemCopy,
- mangle_Bytes,
- mangle_ASCIINum,
- mangle_ASCIINumChange,
- mangle_ByteRepeatOverwrite,
- mangle_ByteRepeatInsert,
- mangle_Magic,
- mangle_StaticDict,
- mangle_ConstFeedbackDict,
- mangle_RandomOverwrite,
- mangle_RandomInsert,
- mangle_Splice,
-
- };
-
- if (run->mutationsPerRun == 0U) { return; }
- if (run->dynfile->size == 0U) {
-
- mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
-
- }
-
- uint64_t changesCnt;
-
- if (speed_factor < 5) {
-
- changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
-
- } else if (speed_factor < 10) {
-
- changesCnt = run->global->mutate.mutationsPerRun;
-
- } else {
-
- changesCnt = HF_MIN(speed_factor, 12);
- changesCnt = HF_MAX(changesCnt, run->global->mutate.mutationsPerRun);
-
- }
-
- /* If last coverage acquisition was more than 5 secs ago, use splicing more
- * frequently */
- if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
-
- if (util_rnd64() % 2) {
-
- mangle_Splice(run, run->global->cfg.only_printable);
-
+void mangle_mangleContent(run_t* run, int speed_factor) {
+ static void (*const mangleFuncs[])(run_t * run, bool printable) = {
+ mangle_Shrink,
+ mangle_Expand,
+ mangle_Bit,
+ mangle_IncByte,
+ mangle_DecByte,
+ mangle_NegByte,
+ mangle_AddSub,
+ mangle_MemSet,
+ mangle_MemClr,
+ mangle_MemSwap,
+ mangle_MemCopy,
+ mangle_Bytes,
+ mangle_ASCIINum,
+ mangle_ASCIINumChange,
+ mangle_ByteRepeat,
+ mangle_Magic,
+ mangle_StaticDict,
+ mangle_ConstFeedbackDict,
+ mangle_RandomBuf,
+ mangle_Splice,
+ };
+
+ if (run->mutationsPerRun == 0U) {
+ return;
+ }
+ if (run->dynfile->size == 0U) {
+ mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
}
- }
-
- for (uint64_t x = 0; x < changesCnt; x++) {
+ uint64_t changesCnt = run->global->mutate.mutationsPerRun;
- uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
- mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
+ if (speed_factor < 5) {
+ changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
+ } else if (speed_factor < 10) {
+ changesCnt = run->global->mutate.mutationsPerRun;
+ } else {
+ changesCnt = HF_MIN(speed_factor, 10);
+ changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
+ }
- }
+ /* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */
+ if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
+ if (util_rnd64() & 0x1) {
+ mangle_Splice(run, run->global->cfg.only_printable);
+ }
+ }
- wmb();
+ for (uint64_t x = 0; x < changesCnt; x++) {
+ if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
+ /*
+ * mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary
+ * exists. If so, give it 50% chance of being used among all mangling functions.
+ */
+ mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable);
+ } else {
+ uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
+ mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
+ }
+ }
+ wmb();
}
-
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 477498d0..c4347baf 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -16,24 +16,32 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
to be placed in the source code.
Check out instrumentation/README.instrument_list.md
- afl-fuzz
- - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on start
- the target map size
+ - Making AFL_MAP_SIZE (mostly) obsolete - afl-fuzz now learns on
+ start the target map size
- upgraded cmplog/redqueen: solving for floating point, solving
transformations (e.g. toupper, tolower, to/from hex, xor,
arithmetics, etc.). This is costly hence new command line option
- `-l` that sets the intensity (values 1 to 3). Recommended is 1 or 2.
- - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial testcases from
- `-i` or resumes (as these have most likely already been done)
+ `-l` that sets the intensity (values 1 to 3). Recommended is 2.
+ - added `AFL_CMPLOG_ONLY_NEW` to not use cmplog on initial seeds
+ from `-i` or resumes (these have most likely already been done)
- fix crash for very, very fast targets+systems (thanks to mhlakhani
for reporting)
- on restarts (`-i`)/autoresume (AFL_AUTORESUME) the stats are now
reloaded and used, thanks to Vimal Joseph for this patch!
- - if deterministic mode is active (`-D`, or `-M` without `-d`) then we sync
- after every queue entry as this can take very long time otherwise
+ - changed the meaning of '+' of the '-t' option, it now means to
+ auto-calculate the timeout with the value given being the max
+ timeout. The original meaning of skipping timeouts instead of
+ abort is now inherent to the -t option.
+ - if deterministic mode is active (`-D`, or `-M` without `-d`) then
+ we sync after every queue entry as this can take very long time
+ otherwise
+ - added minimum SYNC_TIME to include/config.h (30 minutes default)
- better detection if a target needs a large shared map
- fix for `-Z`
+ - fixed a few crashes
- switched to an even faster RNG
- added hghwng's patch for faster trace map analysis
+ - printing suggestions for mistyped `AFL_` env variables
- afl-cc
- allow instrumenting LLVMFuzzerTestOneInput
- fixed endless loop for allow/blocklist lines starting with a
@@ -61,12 +69,13 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- Improved rust bindings
- Added a new example harness to compare python, c, and rust bindings
- afl-cmin and afl-showmap now support the -f option
+ - afl_plot now also generates a graph on the discovered edges
- changed default: no memory limit for afl-cmin and afl-cmin.bash
- warn on any _AFL and __AFL env vars.
- set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars.
- added dummy Makefile to instrumentation/
- Updated utils/afl_frida to be 5% faster, 7% on x86_x64
- - Added AFL_KILL_SIGNAL env variable (thanks @v-p-b)
+ - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b)
- @Edznux added a nice documentation on how to use rpc.statsd with
afl++ in docs/rpc_statsd.md, thanks!
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 1d5ec1f0..3531d672 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -570,6 +570,7 @@ typedef struct afl_state {
blocks_eff_total, /* Blocks subject to effector maps */
blocks_eff_select, /* Blocks selected as fuzzable */
start_time, /* Unix start time (ms) */
+ last_sync_time, /* Time of last sync */
last_path_time, /* Time for most recent path (ms) */
last_crash_time, /* Time for most recent crash (ms) */
last_hang_time; /* Time for most recent hang (ms) */
@@ -649,6 +650,7 @@ typedef struct afl_state {
u32 cmplog_max_filesize;
u32 cmplog_lvl;
u32 colorize_success;
+ u8 cmplog_enable_arith, cmplog_enable_transform;
struct afl_pass_stat *pass_stats;
struct cmp_map * orig_cmp_map;
@@ -1070,8 +1072,8 @@ void destroy_extras(afl_state_t *);
void load_stats_file(afl_state_t *);
void write_setup_file(afl_state_t *, u32, char **);
-void write_stats_file(afl_state_t *, double, double, double);
-void maybe_update_plot_file(afl_state_t *, double, double);
+void write_stats_file(afl_state_t *, u32, double, double, double);
+void maybe_update_plot_file(afl_state_t *, u32, double, double);
void show_stats(afl_state_t *);
void show_init_stats(afl_state_t *);
diff --git a/include/common.h b/include/common.h
index bb8831f2..cd728536 100644
--- a/include/common.h
+++ b/include/common.h
@@ -39,6 +39,7 @@
#define STRINGIFY_VAL_SIZE_MAX (16)
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin);
+void print_suggested_envs(char *mispelled_env);
void check_environment_vars(char **env);
char **argv_cpy_dup(int argc, char **argv);
diff --git a/include/config.h b/include/config.h
index 9f7db04d..439f4d2f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -42,27 +42,22 @@
*
*/
-/* Enable arithmetic compare solving for both branches */
-#define CMPLOG_SOLVE_ARITHMETIC
-
-/* Enable transform following (XOR/ADD/SUB manipulations, hex en/decoding) */
-#define CMPLOG_SOLVE_TRANSFORM
-
-/* if TRANSFORM is enabled, this additionally enables base64 en/decoding */
+/* if TRANSFORM is enabled with '-l T', this additionally enables base64
+ encoding/decoding */
// #define CMPLOG_SOLVE_TRANSFORM_BASE64
/* If a redqueen pass finds more than one solution, try to combine them? */
#define CMPLOG_COMBINE
-/* Minimum % of the corpus to perform cmplog on. Default: 20% */
-#define CMPLOG_CORPUS_PERCENT 20U
+/* Minimum % of the corpus to perform cmplog on. Default: 10% */
+#define CMPLOG_CORPUS_PERCENT 10U
/* Number of potential positions from which we decide if cmplog becomes
- useless, default 16384 */
-#define CMPLOG_POSITIONS_MAX 16384U
+ useless, default 8096 */
+#define CMPLOG_POSITIONS_MAX 8096U
-/* Maximum allowed fails per CMP value. Default: 32 * 3 */
-#define CMPLOG_FAIL_MAX 96
+/* Maximum allowed fails per CMP value. Default: 128 */
+#define CMPLOG_FAIL_MAX 128
/* Now non-cmplog configuration options */
@@ -285,6 +280,11 @@
#define SYNC_INTERVAL 8
+/* Sync time (minimum time between syncing in ms, time is halfed for -M main
+ nodes) - default is 30 minutes: */
+
+#define SYNC_TIME (30 * 60 * 1000)
+
/* Output directory reuse grace period (minutes): */
#define OUTPUT_GRACE 25
diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md
index a2814173..81c82c4b 100644
--- a/instrumentation/README.lto.md
+++ b/instrumentation/README.lto.md
@@ -88,16 +88,35 @@ apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
### Building llvm yourself (version 12)
Building llvm from github takes quite some long time and is not painless:
-```
+```sh
sudo apt install binutils-dev # this is *essential*!
-git clone https://github.com/llvm/llvm-project
+git clone --depth=1 https://github.com/llvm/llvm-project
cd llvm-project
mkdir build
cd build
-cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DCMAKE_BUILD_TYPE=Release -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/
-make -j $(nproc)
-export PATH=`pwd`/bin:$PATH
-export LLVM_CONFIG=`pwd`/bin/llvm-config
+
+# Add -G Ninja if ninja-build installed
+# "Building with ninja significantly improves your build time, especially with
+# incremental builds, and improves your memory usage."
+cmake \
+ -DCLANG_INCLUDE_DOCS="OFF" \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DLLVM_BINUTILS_INCDIR=/usr/include/ \
+ -DLLVM_BUILD_LLVM_DYLIB="ON" \
+ -DLLVM_ENABLE_BINDINGS="OFF" \
+ -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;libcxx;libcxxabi;libunwind;lld' \
+ -DLLVM_ENABLE_WARNINGS="OFF" \
+ -DLLVM_INCLUDE_BENCHMARKS="OFF" \
+ -DLLVM_INCLUDE_DOCS="OFF" \
+ -DLLVM_INCLUDE_EXAMPLES="OFF" \
+ -DLLVM_INCLUDE_TESTS="OFF" \
+ -DLLVM_LINK_LLVM_DYLIB="ON" \
+ -DLLVM_TARGETS_TO_BUILD="host" \
+ ../llvm/
+cmake --build . --parallel
+export PATH="$(pwd)/bin:$PATH"
+export LLVM_CONFIG="$(pwd)/bin/llvm-config"
+export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
cd /path/to/AFLplusplus/
make
sudo make install
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index dba4dc65..e4aeadfa 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -1653,12 +1653,19 @@ static u8 *get_llvm_stdstring(u8 *string) {
void __cmplog_rtn_gcc_stdstring_cstring(u8 *stdstring, u8 *cstring) {
+ if (unlikely(!__afl_cmp_map)) return;
+ if (!area_is_mapped(stdstring, 32) || !area_is_mapped(cstring, 32)) return;
+
__cmplog_rtn_hook(get_gcc_stdstring(stdstring), cstring);
}
void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
+ if (unlikely(!__afl_cmp_map)) return;
+ if (!area_is_mapped(stdstring1, 32) || !area_is_mapped(stdstring2, 32))
+ return;
+
__cmplog_rtn_hook(get_gcc_stdstring(stdstring1),
get_gcc_stdstring(stdstring2));
@@ -1666,12 +1673,19 @@ void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) {
+ if (unlikely(!__afl_cmp_map)) return;
+ if (!area_is_mapped(stdstring, 32) || !area_is_mapped(cstring, 32)) return;
+
__cmplog_rtn_hook(get_llvm_stdstring(stdstring), cstring);
}
void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
+ if (unlikely(!__afl_cmp_map)) return;
+ if (!area_is_mapped(stdstring1, 32) || !area_is_mapped(stdstring2, 32))
+ return;
+
__cmplog_rtn_hook(get_llvm_stdstring(stdstring1),
get_llvm_stdstring(stdstring2));
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index 6f34ac5a..19ef15f7 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -90,7 +90,7 @@ void dict2file(int fd, u8 *mem, u32 len) {
j = 1;
for (i = 0; i < len; i++) {
- if (isprint(mem[i])) {
+ if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') {
line[j++] = mem[i];
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index b0d4fd45..1152380c 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-213f3b27dd
+e36a30ebca
diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c
index bace0ff6..aff58ad5 100644
--- a/qemu_mode/libqasan/dlmalloc.c
+++ b/qemu_mode/libqasan/dlmalloc.c
@@ -3917,6 +3917,7 @@ static void internal_malloc_stats(mstate m) {
\
} else if (RTCHECK(B == smallbin_at(M, I) || \
\
+ \
(ok_address(M, B) && B->fd == P))) { \
\
F->bk = B; \
@@ -4128,6 +4129,7 @@ static void internal_malloc_stats(mstate m) {
\
} else \
\
+ \
CORRUPTION_ERROR_ACTION(M); \
if (R != 0) { \
\
@@ -4144,6 +4146,7 @@ static void internal_malloc_stats(mstate m) {
\
} else \
\
+ \
CORRUPTION_ERROR_ACTION(M); \
\
} \
@@ -4156,12 +4159,14 @@ static void internal_malloc_stats(mstate m) {
\
} else \
\
+ \
CORRUPTION_ERROR_ACTION(M); \
\
} \
\
} else \
\
+ \
CORRUPTION_ERROR_ACTION(M); \
\
} \
diff --git a/src/afl-cc.c b/src/afl-cc.c
index d41f79a2..c3910e6d 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -1421,6 +1421,14 @@ int main(int argc, char **argv, char **envp) {
}
+ if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT &&
+ (compiler_mode == LLVM || compiler_mode == UNSET)) {
+
+ instrument_mode = INSTRUMENT_CLASSIC;
+ compiler_mode = LLVM;
+
+ }
+
if (!compiler_mode) {
// lto is not a default because outside of afl-cc RANLIB and AR have to
@@ -1699,7 +1707,10 @@ int main(int argc, char **argv, char **envp) {
"Do not be overwhelmed :) afl-cc uses good defaults if no options are "
"selected.\n"
"Read the documentation for FEATURES though, all are good but few are "
- "defaults.\n\n");
+ "defaults.\n"
+ "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast "
+ "with\n"
+ "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n");
exit(1);
@@ -1791,8 +1802,8 @@ int main(int argc, char **argv, char **envp) {
if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC &&
instrument_mode != INSTRUMENT_CFG)
FATAL(
- "CTX and NGRAM instrumentation options can only be used with CFG "
- "(recommended) and CLASSIC instrumentation modes!");
+ "CTX and NGRAM instrumentation options can only be used with LLVM and "
+ "CFG or CLASSIC instrumentation modes!");
if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO"))
FATAL(
diff --git a/src/afl-common.c b/src/afl-common.c
index 589aac71..078ffb9d 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -518,6 +518,141 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
}
+static inline unsigned int helper_min3(unsigned int a, unsigned int b,
+ unsigned int c) {
+
+ return a < b ? (a < c ? a : c) : (b < c ? b : c);
+
+}
+
+// from
+// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
+static int string_distance_levenshtein(char *s1, char *s2) {
+
+ unsigned int s1len, s2len, x, y, lastdiag, olddiag;
+ s1len = strlen(s1);
+ s2len = strlen(s2);
+ unsigned int column[s1len + 1];
+ column[s1len] = 1;
+
+ for (y = 1; y <= s1len; y++)
+ column[y] = y;
+ for (x = 1; x <= s2len; x++) {
+
+ column[0] = x;
+ for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
+
+ olddiag = column[y];
+ column[y] = helper_min3(column[y] + 1, column[y - 1] + 1,
+ lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1));
+ lastdiag = olddiag;
+
+ }
+
+ }
+
+ return column[s1len];
+
+}
+
+#define ENV_SIMILARITY_TRESHOLD 3
+
+void print_suggested_envs(char *mispelled_env) {
+
+ size_t env_name_len =
+ strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix
+ char *env_name = ck_alloc(env_name_len + 1);
+ memcpy(env_name, mispelled_env + 4, env_name_len);
+
+ char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *));
+ int found = 0;
+
+ int j;
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ char *afl_env = afl_environment_variables[j] + 4;
+ int distance = string_distance_levenshtein(afl_env, env_name);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+ found = 1;
+
+ }
+
+ }
+
+ if (found) goto cleanup;
+
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ char * afl_env = afl_environment_variables[j] + 4;
+ size_t afl_env_len = strlen(afl_env);
+ char * reduced = ck_alloc(afl_env_len + 1);
+
+ size_t start = 0;
+ while (start < afl_env_len) {
+
+ size_t end = start + strcspn(afl_env + start, "_") + 1;
+ memcpy(reduced, afl_env, start);
+ if (end < afl_env_len)
+ memcpy(reduced + start, afl_env + end, afl_env_len - end);
+ reduced[afl_env_len - end + start] = 0;
+
+ int distance = string_distance_levenshtein(reduced, env_name);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+ found = 1;
+
+ }
+
+ start = end;
+
+ };
+
+ ck_free(reduced);
+
+ }
+
+ if (found) goto cleanup;
+
+ char * reduced = ck_alloc(env_name_len + 1);
+ size_t start = 0;
+ while (start < env_name_len) {
+
+ size_t end = start + strcspn(env_name + start, "_") + 1;
+ memcpy(reduced, env_name, start);
+ if (end < env_name_len)
+ memcpy(reduced + start, env_name + end, env_name_len - end);
+ reduced[env_name_len - end + start] = 0;
+
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ int distance = string_distance_levenshtein(
+ afl_environment_variables[j] + 4, reduced);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+
+ }
+
+ }
+
+ start = end;
+
+ };
+
+ ck_free(reduced);
+
+cleanup:
+ ck_free(env_name);
+ ck_free(seen);
+
+}
+
void check_environment_vars(char **envp) {
if (be_quiet) { return; }
@@ -587,6 +722,8 @@ void check_environment_vars(char **envp) {
WARNF("Mistyped AFL environment variable: %s", env);
issue_detected = 1;
+ print_suggested_envs(env);
+
}
}
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 702e732d..3dbc4c65 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -882,32 +882,23 @@ void perform_dry_run(afl_state_t *afl) {
if (afl->timeout_given) {
- /* The -t nn+ syntax in the command line sets afl->timeout_given to
- '2' and instructs afl-fuzz to tolerate but skip queue entries that
- time out. */
+ /* if we have a timeout but a timeout value was given then always
+ skip. The '+' meaning has been changed! */
+ WARNF("Test case results in a timeout (skipping)");
+ ++cal_failures;
+ q->cal_failed = CAL_CHANCES;
+ q->disabled = 1;
+ q->perf_score = 0;
- if (afl->timeout_given > 1) {
+ if (!q->was_fuzzed) {
- WARNF("Test case results in a timeout (skipping)");
- q->cal_failed = CAL_CHANCES;
- ++cal_failures;
- break;
+ q->was_fuzzed = 1;
+ --afl->pending_not_fuzzed;
+ --afl->active_paths;
}
- SAYF("\n" cLRD "[-] " cRST
- "The program took more than %u ms to process one of the initial "
- "test cases.\n"
- " Usually, the right thing to do is to relax the -t option - "
- "or to delete it\n"
- " altogether and allow the fuzzer to auto-calibrate. That "
- "said, if you know\n"
- " what you are doing and want to simply skip the unruly test "
- "cases, append\n"
- " '+' at the end of the value passed to -t ('-t %u+').\n",
- afl->fsrv.exec_tmout, afl->fsrv.exec_tmout);
-
- FATAL("Test case '%s' results in a timeout", fn);
+ break;
} else {
@@ -1060,13 +1051,22 @@ void perform_dry_run(afl_state_t *afl) {
p->perf_score = 0;
u32 i = 0;
- while (unlikely(afl->queue_buf[i]->disabled)) {
+ while (unlikely(i < afl->queued_paths && afl->queue_buf[i] &&
+ afl->queue_buf[i]->disabled)) {
++i;
}
- afl->queue = afl->queue_buf[i];
+ if (i < afl->queued_paths && afl->queue_buf[i]) {
+
+ afl->queue = afl->queue_buf[i];
+
+ } else {
+
+ afl->queue = afl->queue_buf[0];
+
+ }
afl->max_depth = 0;
for (i = 0; i < afl->queued_paths; i++) {
@@ -2017,7 +2017,7 @@ void setup_dirs_fds(afl_state_t *afl) {
fprintf(afl->fsrv.plot_file,
"# unix_time, cycles_done, cur_path, paths_total, "
"pending_total, pending_favs, map_size, unique_crashes, "
- "unique_hangs, max_depth, execs_per_sec\n");
+ "unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
fflush(afl->fsrv.plot_file);
/* ignore errors */
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 3ac7ba11..1ab5f996 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -30,7 +30,6 @@
//#define _DEBUG
//#define CMPLOG_INTROSPECTION
-#define CMPLOG_COMBINE
// CMP attribute enum
enum {
@@ -205,14 +204,31 @@ static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
case '\t':
c = ' ';
break;
- /*
- case '\r':
- case '\n':
- // nothing ...
- break;
- */
+ case '\r':
+ c = '\n';
+ break;
+ case '\n':
+ c = '\r';
+ break;
+ case 0:
+ c = 1;
+ break;
+ case 1:
+ c = 0;
+ break;
+ case 0xff:
+ c = 0;
+ break;
default:
- c = (buf[i] ^ 0xff);
+ if (buf[i] < 32) {
+
+ c = (buf[i] ^ 0x1f);
+
+ } else {
+
+ c = (buf[i] ^ 0x7f); // we keep the highest bit
+
+ }
}
@@ -506,7 +522,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
}
-#ifdef CMPLOG_SOLVE_TRANSFORM
+//#ifdef CMPLOG_SOLVE_TRANSFORM
static int strntoll(const char *str, size_t sz, char **end, int base,
long long *out) {
@@ -591,7 +607,7 @@ static int is_hex(const char *str) {
}
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// tests 4 bytes at location
static int is_base64(const char *str) {
@@ -704,10 +720,10 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
}
- #endif
-
#endif
+//#endif
+
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern,
u64 changed_val, u8 attr, u32 idx, u32 taint_len,
@@ -731,9 +747,9 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// o_pattern, pattern, repl, changed_val, idx, taint_len,
// h->shape + 1, attr);
-#ifdef CMPLOG_SOLVE_TRANSFORM
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
- if (lvl & LVL3) {
+ if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u8 * endptr;
u8 use_num = 0, use_unum = 0;
@@ -754,11 +770,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- #ifdef _DEBUG
+#ifdef _DEBUG
if (idx == 0)
fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n",
afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern);
- #endif
+#endif
// num is likely not pattern as atoi("AAA") will be zero...
if (use_num && ((u64)num == pattern || !num)) {
@@ -1043,7 +1059,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
-#endif
+ //#endif
// we only allow this for ascii2integer (above) so leave if this is the case
if (unlikely(pattern == o_pattern)) { return 0; }
@@ -1198,8 +1214,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// 16 = modified float, 32 = modified integer (modified = wont match
// in original buffer)
-#ifdef CMPLOG_SOLVE_ARITHMETIC
- if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; }
+ //#ifdef CMPLOG_SOLVE_ARITHMETIC
+ if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
+
+ return 0;
+
+ }
if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
@@ -1304,11 +1324,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
double *f = (double *)&repl;
float g = (float)*f;
repl_new = 0;
- #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
memcpy((char *)&repl_new, (char *)&g, 4);
- #else
+#else
memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
- #endif
+#endif
changed_val = repl_new;
h->shape = 3; // modify shape
@@ -1363,7 +1383,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
-#endif /* CMPLOG_SOLVE_ARITHMETIC */
+ //#endif /* CMPLOG_SOLVE_ARITHMETIC
return 0;
@@ -1522,7 +1542,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
for (k = 0; k < size; ++k) {
#else
- u32 off = 16 - size;
+ u32 off = 16 - size;
for (k = 16 - size; k < 16; ++k) {
#endif
@@ -1840,9 +1860,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
#ifndef CMPLOG_COMBINE
(void)(cbuf);
#endif
-#ifndef CMPLOG_SOLVE_TRANSFORM
- (void)(changed_val);
-#endif
+ //#ifndef CMPLOG_SOLVE_TRANSFORM
+ // (void)(changed_val);
+ //#endif
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
@@ -1922,16 +1942,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
-#ifdef CMPLOG_SOLVE_TRANSFORM
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
if (*status == 1) return 0;
- if (lvl & LVL3) {
+ if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
u32 tob64 = 0, fromb64 = 0;
- #endif
+#endif
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
u8 xor_val[32], arith_val[32], tmp[48];
@@ -2027,7 +2047,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
if (i % 3 == 2 && i < 24) {
if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
@@ -2040,7 +2060,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #endif
+#endif
if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) {
@@ -2068,20 +2088,20 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef _DEBUG
+#ifdef _DEBUG
fprintf(stderr,
"RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
"tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
"from_0=%u from_slash=%u from_x=%u\n",
idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
to_slash, to_x, from_0, from_slash, from_x);
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+ #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64,
fromb64);
- #endif
#endif
+#endif
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// input is base64 and converted to binary? convert repl to base64!
if ((i % 4) == 3 && i < 24 && fromb64 > i) {
@@ -2104,7 +2124,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #endif
+#endif
// input is converted to hex? convert repl to binary!
if (i < 16 && tohex > i) {
@@ -2233,16 +2253,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef CMPLOG_COMBINE
+#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); }
- #endif
+#endif
if ((i >= 7 &&
(i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i >
(fromhex + from_0 + from_x + from_slash + 1)
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
&& i > tob64 + 3 && i > fromb64 + 4
- #endif
+#endif
)) ||
repl[i] != changed_val[i] || *status == 1) {
@@ -2256,7 +2276,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
-#endif
+ //#endif
return 0;
@@ -2589,9 +2609,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} else if ((lvl & LVL1)
-#ifdef CMPLOG_SOLVE_TRANSFORM
- || (lvl & LVL3)
-#endif
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
+ || ((lvl & LVL3) && afl->cmplog_enable_transform)
+ //#endif
) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
@@ -2672,7 +2692,7 @@ exit_its:
#else
u32 *v = (u32 *)afl->virgin_bits;
u32 *s = (u32 *)virgin_save;
- u32 i;
+ u32 i;
for (i = 0; i < (afl->shm.map_size >> 2); i++) {
v[i] &= s[i];
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 97cb7415..0b84a542 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -707,6 +707,8 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
+ afl->last_sync_time = get_cur_time();
+
}
/* Trim all new test cases to save cycles when doing deterministic checks. The
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 5040e3ef..3d36e712 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -486,6 +486,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
WARNF("Mistyped AFL environment variable: %s", env);
issue_detected = 1;
+ print_suggested_envs(env);
+
}
}
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 66efeb20..bd856088 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -185,15 +185,14 @@ void load_stats_file(afl_state_t *afl) {
/* Update stats file for unattended monitoring. */
-void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
- double eps) {
+void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
+ double stability, double eps) {
#ifndef __HAIKU__
struct rusage rus;
#endif
u64 cur_time = get_cur_time();
- u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
u8 fn[PATH_MAX];
FILE *f;
@@ -353,9 +352,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
/* Update the plot file if there is a reason to. */
-void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
+void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
+ double eps) {
- if (unlikely(afl->plot_prev_qp == afl->queued_paths &&
+ if (unlikely(afl->stop_soon) ||
+ unlikely(afl->plot_prev_qp == afl->queued_paths &&
afl->plot_prev_pf == afl->pending_favored &&
afl->plot_prev_pnf == afl->pending_not_fuzzed &&
afl->plot_prev_ce == afl->current_entry &&
@@ -384,16 +385,16 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
/* Fields in the file:
unix_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed,
- favored_not_fuzzed, afl->unique_crashes, afl->unique_hangs, afl->max_depth,
- execs_per_sec */
+ favored_not_fuzzed, unique_crashes, unique_hangs, max_depth,
+ execs_per_sec, edges_found */
- fprintf(
- afl->fsrv.plot_file,
- "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu\n",
- get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry,
- afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored,
- bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps,
- afl->plot_prev_ed); /* ignore errors */
+ fprintf(afl->fsrv.plot_file,
+ "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
+ "%u\n",
+ get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry,
+ afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored,
+ bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth,
+ eps, afl->plot_prev_ed, t_bytes); /* ignore errors */
fflush(afl->fsrv.plot_file);
@@ -532,7 +533,8 @@ void show_stats(afl_state_t *afl) {
if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
afl->stats_last_stats_ms = cur_ms;
- write_stats_file(afl, t_byte_ratio, stab_ratio, afl->stats_avg_exec);
+ write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
+ afl->stats_avg_exec);
save_auto(afl);
write_bitmap(afl);
@@ -555,7 +557,7 @@ void show_stats(afl_state_t *afl) {
if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
afl->stats_last_plot_ms = cur_ms;
- maybe_update_plot_file(afl, t_byte_ratio, afl->stats_avg_exec);
+ maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
}
@@ -1217,7 +1219,7 @@ void show_init_stats(afl_state_t *afl) {
stringify_int(IB(0), min_us), stringify_int(IB(1), max_us),
stringify_int(IB(2), avg_us));
- if (!afl->timeout_given) {
+ if (afl->timeout_given != 1) {
/* Figure out the appropriate timeout. The basic idea is: 5x average or
1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second.
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8eb3625b..a02eadb2 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -103,7 +103,10 @@ static void usage(u8 *argv0, int more_help) {
" quad -- see docs/power_schedules.md\n"
" -f file - location read by the fuzzed program (default: stdin "
"or @@)\n"
- " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n"
+ " -t msec - timeout for each run (auto-scaled, default %u ms). "
+ "Add a '+'\n"
+ " to auto-calculate the timeout, the value being the "
+ "maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
@@ -122,10 +125,10 @@ static void usage(u8 *argv0, int more_help) {
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
" if using QEMU, just use -c 0.\n"
- " -l cmplog_level - set the complexity/intensivity of CmpLog.\n"
- " Values: 1 (basic), 2 (larger files) and 3 "
- "(transform)\n\n"
-
+ " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
+ " 1=small files (default), 2=larger files, 3=all "
+ "files,\n"
+ " A=arithmetic solving, T=transformational solving.\n\n"
"Fuzzing behavior settings:\n"
" -Z - sequential queue selection instead of weighted "
"random\n"
@@ -137,8 +140,8 @@ static void usage(u8 *argv0, int more_help) {
"Testing settings:\n"
" -s seed - use a fixed seed for the RNG\n"
- " -V seconds - fuzz for a specific time then terminate\n"
- " -E execs - fuzz for a approx. no of total executions then "
+ " -V seconds - fuzz for a specified time then terminate\n"
+ " -E execs - fuzz for an approx. no. of total executions then "
"terminate\n"
" Note: not precise and can have several more "
"executions.\n\n"
@@ -812,13 +815,36 @@ int main(int argc, char **argv_orig, char **envp) {
case 'l': {
- if (optarg) { afl->cmplog_lvl = atoi(optarg); }
- if (afl->cmplog_lvl < 1 || afl->cmplog_lvl > CMPLOG_LVL_MAX) {
+ if (!optarg) { FATAL("missing parameter for 'l'"); }
+ char *c = optarg;
+ while (*c) {
- FATAL(
- "Bad complog level value, accepted values are 1 (default), 2 and "
- "%u.",
- CMPLOG_LVL_MAX);
+ switch (*c) {
+
+ case '0':
+ case '1':
+ afl->cmplog_lvl = 1;
+ break;
+ case '2':
+ afl->cmplog_lvl = 2;
+ break;
+ case '3':
+ afl->cmplog_lvl = 3;
+ break;
+ case 'a':
+ case 'A':
+ afl->cmplog_enable_arith = 1;
+ break;
+ case 't':
+ case 'T':
+ afl->cmplog_enable_transform = 1;
+ break;
+ default:
+ FATAL("Unknown option value '%c' in -l %s", *c, optarg);
+
+ }
+
+ ++c;
}
@@ -1428,7 +1454,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!afl->timeout_given) { find_timeout(afl); }
+ if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
!afl->in_place_resume) {
@@ -1682,20 +1708,49 @@ int main(int argc, char **argv_orig, char **envp) {
cull_queue(afl);
- if (!afl->pending_not_fuzzed) {
+ // ensure we have at least one seed that is not disabled.
+ u32 entry, valid_seeds = 0;
+ for (entry = 0; entry < afl->queued_paths; ++entry)
+ if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
+
+ if (!afl->pending_not_fuzzed || !valid_seeds) {
FATAL("We need at least one valid input seed that does not crash!");
}
+ if (afl->timeout_given == 2) { // -t ...+ option
+
+ if (valid_seeds == 1) {
+
+ WARNF(
+ "Only one valid seed is present, auto-calculating the timeout is "
+ "disabled!");
+ afl->timeout_given = 1;
+
+ } else {
+
+ u64 max_ms = 0;
+
+ for (entry = 0; entry < afl->queued_paths; ++entry)
+ if (!afl->queue_buf[entry]->disabled)
+ if (afl->queue_buf[entry]->exec_us > max_ms)
+ max_ms = afl->queue_buf[entry]->exec_us;
+
+ afl->fsrv.exec_tmout = max_ms;
+
+ }
+
+ }
+
show_init_stats(afl);
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
afl->start_time = get_cur_time();
if (afl->in_place_resume || afl->afl_env.afl_autoresume) load_stats_file(afl);
- write_stats_file(afl, 0, 0, 0);
- maybe_update_plot_file(afl, 0, 0);
+ write_stats_file(afl, 0, 0, 0, 0);
+ maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
if (afl->stop_soon) { goto stop_fuzzing; }
@@ -1745,12 +1800,15 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->old_seed_selection)) {
afl->current_entry = 0;
- while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) {
+ while (unlikely(afl->current_entry < afl->queued_paths &&
+ afl->queue_buf[afl->current_entry]->disabled)) {
++afl->current_entry;
}
+ if (afl->current_entry >= afl->queued_paths) { afl->current_entry = 0; }
+
afl->queue_cur = afl->queue_buf[afl->current_entry];
if (unlikely(seek_to)) {
@@ -1953,15 +2011,24 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->is_main_node)) {
- if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
+ if (unlikely(get_cur_time() >
+ (SYNC_TIME >> 1) + afl->last_sync_time)) {
+
+ if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
- sync_fuzzers(afl);
+ sync_fuzzers(afl);
+
+ }
}
} else {
- if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+ if (unlikely(get_cur_time() > SYNC_TIME + afl->last_sync_time)) {
+
+ if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+
+ }
}
@@ -1976,12 +2043,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
write_bitmap(afl);
- maybe_update_plot_file(afl, 0, 0);
+ maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
stop_fuzzing:
- write_stats_file(afl, 0, 0, 0);
+ write_stats_file(afl, 0, 0, 0, 0);
afl->force_ui_update = 1; // ensure the screen is reprinted
show_stats(afl); // print the screen one last time
diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh
index 0cd6ef40..85578d55 100755
--- a/test/test-qemu-mode.sh
+++ b/test/test-qemu-mode.sh
@@ -39,14 +39,7 @@ test -e ../afl-qemu-trace && {
$ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds"
{
{
- if file test-instr | grep -q "32-bit"; then
- # for 32-bit reduce 8 nibbles to the lower 7 nibbles
- ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'`
- else
- # for 64-bit reduce 16 nibbles to the lower 9 nibbles
- ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'`
- fi
- export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}`
+ export AFL_ENTRYPOINT=`printf 1 | AFL_DEBUG=1 ../afl-qemu-trace ./test-instr 2>&1 >/dev/null | awk '/forkserver/{print $4; exit}'`
$ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr)
../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr
unset AFL_ENTRYPOINT