mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 19:08:08 +00:00
small improvements to Marcel's patch, fix laf-intel + redqueen crashes
This commit is contained in:
@ -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
|
||||
|
@ -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? */
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user