small improvements to Marcel's patch, fix laf-intel + redqueen crashes
MODIFY
docs/Changelog.md
docs/Changelog.md
@@ -14,6 +14,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- all compilers combined to afl-cc which emulates the previous ones
- afl-llvm/gcc-rt.o merged into afl-compiler-rt.o
- afl-fuzz
+ - Marcel Boehme submitted a patch that improves all AFFast schedules :)
- reading testcases from -i now descends into subdirectories
- allow up to 4 -x command line options
- loaded extras now have a duplicate protection

MODIFY
include/afl-fuzz.h
include/afl-fuzz.h
@@ -151,7 +151,8 @@ struct queue_entry {
is_ascii; /* Is the input just ascii text? */
u32 bitmap_size, /* Number of bits set in bitmap */
- fuzz_level; /* Number of fuzzing iterations */
+ fuzz_level, /* Number of fuzzing iterations */
+ n_fuzz_entry; /* offset in n_fuzz */
u64 exec_us, /* Execution time (us) */
handicap, /* Number of queue cycles behind */
@@ -491,7 +492,7 @@ typedef struct afl_state {
u8 *var_bytes; /* Bytes that appear to be variable */
- #define n_fuzz_size (1 << 21)
+#define N_FUZZ_SIZE (1 << 21)
u32 *n_fuzz;
volatile u8 stop_soon, /* Ctrl-C pressed? */

MODIFY
instrumentation/afl-llvm-dict2file.so.cc
instrumentation/afl-llvm-dict2file.so.cc
@@ -381,8 +381,9 @@ bool AFLdict2filePass::runOnModule(Module &M) {
if (debug)
fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
- FuncName.c_str(), (void*)Str1P, Str1P->getName().str().c_str(),
- Str1.c_str(), HasStr1 == true ? "true" : "false", (void*)Str2P,
+ FuncName.c_str(), (void *)Str1P,
+ Str1P->getName().str().c_str(), Str1.c_str(),
+ HasStr1 == true ? "true" : "false", (void *)Str2P,
Str2P->getName().str().c_str(), Str2.c_str(),
HasStr2 == true ? "true" : "false");
@@ -436,7 +437,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
valueMap[Str1P] = new std::string(Str2);
if (debug)
- fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(), (void*)Str1P);
+ fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(),
+ (void *)Str1P);
continue;
}
@@ -455,7 +457,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
Str2 = *strng;
HasStr2 = true;
if (debug)
- fprintf(stderr, "Filled2: %s for %p\n", strng->c_str(), (void*)Str2P);
+ fprintf(stderr, "Filled2: %s for %p\n", strng->c_str(),
+ (void *)Str2P);
}
@@ -497,7 +500,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
Str1 = *strng;
HasStr1 = true;
if (debug)
- fprintf(stderr, "Filled1: %s for %p\n", strng->c_str(), (void*)Str1P);
+ fprintf(stderr, "Filled1: %s for %p\n", strng->c_str(),
+ (void *)Str1P);
}

MODIFY
instrumentation/cmplog-instructions-pass.cc
instrumentation/cmplog-instructions-pass.cc
@@ -210,7 +210,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
}
if (!icomps.size()) return false;
- if (!be_quiet) errs() << "Hooking " << icomps.size() << " cmp instructions\n";
+ // if (!be_quiet) errs() << "Hooking " << icomps.size() << " cmp
+ // instructions\n";
for (auto &selectcmpInst : icomps) {
@@ -259,8 +260,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
bool CmpLogInstructions::runOnModule(Module &M) {
if (getenv("AFL_QUIET") == NULL)
- llvm::errs()
- << "Running cmplog-instructions-pass by andreafioraldi@gmail.com\n";
+ printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookInstrs(M);

MODIFY
instrumentation/cmplog-routines-pass.cc
instrumentation/cmplog-routines-pass.cc
@@ -149,9 +149,11 @@ bool CmpLogRoutines::hookRtns(Module &M) {
}
if (!calls.size()) return false;
+ /*
if (!be_quiet)
errs() << "Hooking " << calls.size()
<< " calls with pointers as arguments\n";
+ */
for (auto &callInst : calls) {
@@ -179,8 +181,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
bool CmpLogRoutines::runOnModule(Module &M) {
if (getenv("AFL_QUIET") == NULL)
- llvm::errs()
- << "Running cmplog-routines-pass by andreafioraldi@gmail.com\n";
+ printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookRtns(M);

MODIFY
instrumentation/compare-transform-pass.so.cc
instrumentation/compare-transform-pass.so.cc
@@ -339,8 +339,9 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (!calls.size()) return false;
if (!be_quiet)
- errs() << "Replacing " << calls.size()
- << " calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp\n";
+ printf(
+ "Replacing %lu calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp\n",
+ calls.size());
for (auto &callInst : calls) {
@@ -426,11 +427,14 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
else
unrollLen = constStrLen;
+ /*
if (!be_quiet)
errs() << callInst->getCalledFunction()->getName() << ": unroll len "
<< unrollLen
- << ((isSizedcmp && !isConstSized) ? ", variable n" : "") << ": "
+ << ((isSizedcmp && !isConstSized) ? ", variable n" : "") << ":
+ "
<< ConstStr << "\n";
+ */
/* split before the call instruction */
BasicBlock *bb = callInst->getParent();
@@ -556,10 +560,12 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool CompareTransform::runOnModule(Module &M) {
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
- llvm::errs() << "Running compare-transform-pass by laf.intel@gmail.com, "
- "extended by heiko@hexco.de\n";
+ printf(
+ "Running compare-transform-pass by laf.intel@gmail.com, extended by "
+ "heiko@hexco.de\n");
else
be_quiet = 1;
+
transformCmps(M, true, true, true, true, true);
verifyModule(M);

MODIFY
instrumentation/split-compares-pass.so.cc
instrumentation/split-compares-pass.so.cc
@@ -1262,8 +1262,9 @@ bool SplitComparesTransform::runOnModule(Module &M) {
if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
getenv("AFL_DEBUG") != NULL) {
- errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
- "heiko@hexco.de\n";
+ printf(
+ "Split-compare-pass by laf.intel@gmail.com, extended by "
+ "heiko@hexco.de\n");
} else {
@@ -1275,6 +1276,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
count = splitFPCompares(M);
+ /*
if (!be_quiet) {
errs() << "Split-floatingpoint-compare-pass: " << count
@@ -1282,6 +1284,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}
+ */
simplifyFPCompares(M);
}
@@ -1294,10 +1297,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
case 64:
count = splitIntCompares(M, bitw);
+ /*
if (!be_quiet)
- errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
+ errs() << "Split-integer-compare-pass " << bitw << "bit: " <<
+ count
<< " split\n";
-
+ */
bitw >>= 1;
#if LLVM_VERSION_MAJOR > 3 || \
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
@@ -1305,10 +1310,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
#endif
case 32:
count = splitIntCompares(M, bitw);
+ /*
if (!be_quiet)
- errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
+ errs() << "Split-integer-compare-pass " << bitw << "bit: " <<
+ count
<< " split\n";
-
+ */
bitw >>= 1;
#if LLVM_VERSION_MAJOR > 3 || \
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 7)
@@ -1316,15 +1323,17 @@ bool SplitComparesTransform::runOnModule(Module &M) {
#endif
case 16:
count = splitIntCompares(M, bitw);
+ /*
if (!be_quiet)
- errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
+ errs() << "Split-integer-compare-pass " << bitw << "bit: " <<
+ count
<< " split\n";
-
+ */
bitw >>= 1;
break;
default:
- if (!be_quiet) errs() << "NOT Running split-compare-pass \n";
+ // if (!be_quiet) errs() << "NOT Running split-compare-pass \n";
return false;
break;

MODIFY
instrumentation/split-switches-pass.so.cc
instrumentation/split-switches-pass.so.cc
@@ -327,10 +327,11 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
}
if (!switches.size()) return false;
+ /*
if (!be_quiet)
errs() << "Rewriting " << switches.size() << " switch statements "
<< "\n";
-
+ */
for (auto &SI : switches) {
BasicBlock *CurBlock = SI->getParent();
@@ -341,15 +342,17 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
BasicBlock *Default = SI->getDefaultDest();
unsigned bitw = Val->getType()->getIntegerBitWidth();
+ /*
if (!be_quiet)
errs() << "switch: " << SI->getNumCases() << " cases " << bitw
<< " bit\n";
+ */
/* If there is only the default destination or the condition checks 8 bit or
* less, don't bother with the code below. */
if (!SI->getNumCases() || bitw <= 8) {
- if (!be_quiet) errs() << "skip trivial switch..\n";
+ // if (!be_quiet) errs() << "skip trivial switch..\n";
continue;
}
@@ -415,7 +418,7 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
bool SplitSwitchesTransform::runOnModule(Module &M) {
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
- llvm::errs() << "Running split-switches-pass by laf.intel@gmail.com\n";
+ printf("Running split-switches-pass by laf.intel@gmail.com\n");
else
be_quiet = 1;
splitSwitches(M);

MODIFY
src/afl-fuzz-bitmap.c
src/afl-fuzz-bitmap.c
@@ -556,8 +556,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
/* Saturated increment */
- if (afl->n_fuzz[cksum % n_fuzz_size] < 0xFFFFFFFF)
- afl->n_fuzz[cksum % n_fuzz_size]++;
+ if (afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)
+ afl->n_fuzz[cksum % N_FUZZ_SIZE]++;
}
@@ -597,10 +597,15 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (cksum)
afl->queue_top->exec_cksum = cksum;
else
- afl->queue_top->exec_cksum =
+ cksum = afl->queue_top->exec_cksum =
hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
- afl->n_fuzz[cksum % n_fuzz_size] = 1;
+ if (afl->schedule >= FAST && afl->schedule <= RARE) {
+
+ afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
+ afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
+
+ }
/* Try to calibrate inline; this also calls update_bitmap_score() when
successful. */

MODIFY
src/afl-fuzz-init.c
src/afl-fuzz-init.c
@@ -732,8 +732,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
-
- afl->n_fuzz[cksum % n_fuzz_size] = 1;
+ afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
+ afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
}

MODIFY
src/afl-fuzz-queue.c
src/afl-fuzz-queue.c
@@ -310,7 +310,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE))
fuzz_p2 = 0; // Skip the fuzz_p2 comparison
else if (unlikely(afl->schedule == RARE))
- fuzz_p2 = next_pow2(afl->n_fuzz[q->exec_cksum % n_fuzz_size]);
+ fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]);
else
fuzz_p2 = q->fuzz_level;
@@ -336,7 +336,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
u64 top_rated_fav_factor;
u64 top_rated_fuzz_p2;
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE))
- top_rated_fuzz_p2 = next_pow2(afl->n_fuzz[afl->top_rated[i]->exec_cksum % n_fuzz_size]);
+ top_rated_fuzz_p2 =
+ next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
else
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
@@ -611,7 +612,6 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
double factor = 1.0;
long double fuzz_mu;
-
switch (afl->schedule) {
case EXPLORE:
@@ -634,7 +634,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
struct queue_entry *queue_it = afl->queue;
while (queue_it) {
- fuzz_mu += log2(afl->n_fuzz[q->exec_cksum % n_fuzz_size]);
+ fuzz_mu += log2(afl->n_fuzz[q->n_fuzz_entry]);
n_paths++;
queue_it = queue_it->next;
@@ -645,7 +645,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
fuzz_mu = fuzz_mu / n_paths;
- if (log2(afl->n_fuzz[q->exec_cksum % n_fuzz_size]) > fuzz_mu) {
+ if (log2(afl->n_fuzz[q->n_fuzz_entry]) > fuzz_mu) {
/* Never skip favourites */
if (!q->favored) factor = 0;
@@ -660,7 +660,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
// Don't modify unfuzzed seeds
if (q->fuzz_level == 0) break;
- switch ((u32)log2(afl->n_fuzz[q->exec_cksum % n_fuzz_size])) {
+ switch ((u32)log2(afl->n_fuzz[q->n_fuzz_entry])) {
case 0 ... 1:
factor = 4;
@@ -691,17 +691,17 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
}
- if (q->favored)
- factor *= 1.15;
+ if (q->favored) factor *= 1.15;
break;
case LIN:
- factor = q->fuzz_level / (afl->n_fuzz[q->exec_cksum % n_fuzz_size] + 1);
+ factor = q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1);
break;
case QUAD:
- factor = q->fuzz_level * q->fuzz_level / (afl->n_fuzz[q->exec_cksum % n_fuzz_size] + 1);
+ factor =
+ q->fuzz_level * q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1);
break;
case MMOPT:
@@ -726,8 +726,8 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
perf_score += (q->tc_ref * 10);
// the more often fuzz result paths are equal to this queue entry,
// reduce its value
- perf_score *=
- (1 - (double)((double)afl->n_fuzz[q->exec_cksum % n_fuzz_size] / (double)afl->fsrv.total_execs));
+ perf_score *= (1 - (double)((double)afl->n_fuzz[q->n_fuzz_entry] /
+ (double)afl->fsrv.total_execs));
break;

MODIFY
src/afl-fuzz.c
src/afl-fuzz.c
@@ -939,7 +939,7 @@ int main(int argc, char **argv_orig, char **envp) {
/* Dynamically allocate memory for AFLFast schedules */
if (afl->schedule >= FAST && afl->schedule <= RARE) {
- afl->n_fuzz = ck_alloc(n_fuzz_size * sizeof(u32));
+ afl->n_fuzz = ck_alloc(N_FUZZ_SIZE * sizeof(u32));
}

small improvements to Marcel's patch, fix laf-intel + redqueen crashes