Merge pull request #679 from AFLplusplus/dev

Dev
This commit is contained in:
van Hauser
2021-01-08 15:43:13 +01:00
committed by GitHub
55 changed files with 720 additions and 417 deletions

View File

@ -120,6 +120,7 @@ function usage() {
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \ "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \ "AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \ "AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \ "AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
"AFL_SKIP_BIN_CHECK: skip check for target binary\n" "AFL_SKIP_BIN_CHECK: skip check for target binary\n"
exit 1 exit 1

View File

@ -58,6 +58,11 @@ if [ "$PLATFORM" = "OpenBSD" ] ; then
echo 'System security features cannot be disabled on OpenBSD.' echo 'System security features cannot be disabled on OpenBSD.'
DONE=1 DONE=1
fi fi
if [ "$PLATFORM" = "DragonFly" ] ; then
echo
echo 'System security features cannot be disabled on DragonFly.'
DONE=1
fi
if [ "$PLATFORM" = "NetBSD" ] ; then if [ "$PLATFORM" = "NetBSD" ] ; then
{ {
#echo It is recommended to enable unprivileged users to set cpu affinity #echo It is recommended to enable unprivileged users to set cpu affinity
@ -79,5 +84,14 @@ if [ "$PLATFORM" = "Darwin" ] ; then
fi fi
DONE=1 DONE=1
fi fi
if [ "$PLATFORM" = "Haiku" ] ; then
SETTINGS=~/config/settings/system/debug_server/settings
[ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
echo We change the debug_server default_action from user to silenty kill; \
[ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
echo Settings applied.; \
}
DONE=1
fi
test -z "$DONE" && echo Error: Unknown platform: $PLATFORM test -z "$DONE" && echo Error: Unknown platform: $PLATFORM
exit 0 exit 0

View File

@ -995,7 +995,7 @@ void mangle_mangleContent(run_t *run, int speed_factor) {
} }
uint64_t changesCnt = run->global->mutate.mutationsPerRun; uint64_t changesCnt;
if (speed_factor < 5) { if (speed_factor < 5) {

View File

@ -246,7 +246,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
} }
if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1) if (FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
return false; return false;
// Read traces. // Read traces.
@ -259,8 +259,8 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
if (!CorporaHashes.count(Name)) continue; // not in the corpus. if (!CorporaHashes.count(Name)) continue; // not in the corpus.
NumTraceFiles++; NumTraceFiles++;
// Printf("=== %s\n", Name.c_str()); // Printf("=== %s\n", Name.c_str());
std::ifstream IF(SF.File); std::ifstream IF2(SF.File);
while (std::getline(IF, L, '\n')) { while (std::getline(IF2, L, '\n')) {
size_t FunctionNum = 0; size_t FunctionNum = 0;
std::string DFTString; std::string DFTString;
@ -314,8 +314,8 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
// we then request tags in [0,Size/2) and [Size/2, Size), and so on. // we then request tags in [0,Size/2) and [Size/2, Size), and so on.
// Function number => DFT. // Function number => DFT.
auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File))); auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File)));
std::unordered_map<size_t, Vector<uint8_t>> DFTMap; // std::unordered_map<size_t, Vector<uint8_t>> DFTMap;
std::unordered_set<std::string> Cov; // std::unordered_set<std::string> Cov;
Command Cmd; Command Cmd;
Cmd.addArgument(DFTBinary); Cmd.addArgument(DFTBinary);
Cmd.addArgument(F.File); Cmd.addArgument(F.File);

View File

@ -46,7 +46,7 @@ template<typename T>
fuzzer_allocator() = default; fuzzer_allocator() = default;
template<class U> template<class U>
fuzzer_allocator(const fuzzer_allocator<U>&) {} explicit fuzzer_allocator(const fuzzer_allocator<U>&) {}
template<class Other> template<class Other>
struct rebind { typedef fuzzer_allocator<Other> other; }; struct rebind { typedef fuzzer_allocator<Other> other; };

View File

@ -49,7 +49,7 @@ typedef FixedWord<64> Word;
class DictionaryEntry { class DictionaryEntry {
public: public:
DictionaryEntry() {} DictionaryEntry() {}
DictionaryEntry(Word W) : W(W) {} explicit DictionaryEntry(Word W) : W(W) {}
DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {} DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
const Word &GetW() const { return W; } const Word &GetW() const { return W; }
@ -92,7 +92,7 @@ class Dictionary {
assert(Idx < Size); assert(Idx < Size);
return DE[Idx]; return DE[Idx];
} }
void push_back(DictionaryEntry DE) { void push_back(const DictionaryEntry &DE) {
if (Size < kMaxDictSize) if (Size < kMaxDictSize)
this->DE[Size++] = DE; this->DE[Size++] = DE;
} }

View File

@ -16,7 +16,7 @@
namespace fuzzer { namespace fuzzer {
class Random : public std::minstd_rand { class Random : public std::minstd_rand {
public: public:
Random(unsigned int seed) : std::minstd_rand(seed) {} explicit Random(unsigned int seed) : std::minstd_rand(seed) {}
result_type operator()() { return this->std::minstd_rand::operator()(); } result_type operator()() { return this->std::minstd_rand::operator()(); }
size_t Rand() { return this->operator()(); } size_t Rand() { return this->operator()(); }
size_t RandBool() { return Rand() % 2; } size_t RandBool() { return Rand() % 2; }

View File

@ -145,10 +145,10 @@ private:
}; };
Region *Regions; Region *Regions;
size_t NumRegions; size_t NumRegions;
uint8_t *Start() { return Regions[0].Start; } uint8_t *Start() const { return Regions[0].Start; }
uint8_t *Stop() { return Regions[NumRegions - 1].Stop; } uint8_t *Stop() const { return Regions[NumRegions - 1].Stop; }
size_t Size() { return Stop() - Start(); } size_t Size() const { return Stop() - Start(); }
size_t Idx(uint8_t *P) { size_t Idx(uint8_t *P) const {
assert(P >= Start() && P < Stop()); assert(P >= Start() && P < Stop());
return P - Start(); return P - Start();
} }

View File

@ -9,8 +9,11 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>. sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++3.01a (release) ### Version ++3.01a (dev)
- Mac OS ARM64 support - Mac OS ARM64 support
- New selective instrumentation option with __AFL_COVERAGE_... commands
to be placed in the source code.
Check out instrumentation/README.instrument_list.md
- afl-fuzz - afl-fuzz
- fix crash for very, very fast targets+systems (thanks to mhlakhani - fix crash for very, very fast targets+systems (thanks to mhlakhani
for reporting) for reporting)
@ -20,6 +23,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- allow instrumenting LLVMFuzzerTestOneInput - allow instrumenting LLVMFuzzerTestOneInput
- fixed endless loop for allow/blocklist lines starting with a - fixed endless loop for allow/blocklist lines starting with a
comment (thanks to Zherya for reporting) comment (thanks to Zherya for reporting)
- cmplog/redqueen now also tracks floats/doubles
- added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard
support (less performant than our own), GCC for old afl-gcc and support (less performant than our own), GCC for old afl-gcc and
CLANG for old afl-clang CLANG for old afl-clang
@ -28,7 +32,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
already building with all cores, the gcc plugin needs only one. already building with all cores, the gcc plugin needs only one.
- added dummy Makefile to instrumentation/ - added dummy Makefile to instrumentation/
- Updated utils/afl_frida to be 5% faster - Updated utils/afl_frida to be 5% faster
- Added AFL_KILL_SIGNAL env variable for custom targets (thanks @v-p-b)
### Version ++3.00c (release) ### Version ++3.00c (release)
- llvm_mode/ and gcc_plugin/ moved to instrumentation/ - llvm_mode/ and gcc_plugin/ moved to instrumentation/

View File

@ -350,6 +350,10 @@ checks or alter some of the more exotic semantics of the tool:
- Note that `AFL_POST_LIBRARY` is deprecated, use `AFL_CUSTOM_MUTATOR_LIBRARY` - Note that `AFL_POST_LIBRARY` is deprecated, use `AFL_CUSTOM_MUTATOR_LIBRARY`
instead (see below). instead (see below).
- `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on timeout.
Unless you implement your own targets or instrumentation, you likely don't have to set it.
By default, on timeout and on exit, `SIGKILL` (`AFL_KILL_SIGNAL=9`) will be delivered to the child.
- Setting `AFL_CUSTOM_MUTATOR_LIBRARY` to a shared library with - Setting `AFL_CUSTOM_MUTATOR_LIBRARY` to a shared library with
afl_custom_fuzz() creates additional mutations through this library. afl_custom_fuzz() creates additional mutations through this library.
If afl-fuzz is compiled with Python (which is autodetected during builing If afl-fuzz is compiled with Python (which is autodetected during builing

View File

@ -381,7 +381,7 @@ typedef struct afl_env_vars {
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
*afl_testcache_entries; *afl_testcache_entries, *afl_kill_signal;
} afl_env_vars_t; } afl_env_vars_t;
@ -573,7 +573,7 @@ typedef struct afl_state {
u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */ u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */
s32 stage_cur, stage_max; /* Stage progression */ u32 stage_cur, stage_max; /* Stage progression */
s32 splicing_with; /* Splicing with which test case? */ s32 splicing_with; /* Splicing with which test case? */
u32 main_node_id, main_node_max; /* Main instance job splitting */ u32 main_node_id, main_node_max; /* Main instance job splitting */
@ -648,7 +648,7 @@ typedef struct afl_state {
double last_avg_execs_saved; double last_avg_execs_saved;
/* foreign sync */ /* foreign sync */
#define FOREIGN_SYNCS_MAX 32 #define FOREIGN_SYNCS_MAX 32U
u8 foreign_sync_cnt; u8 foreign_sync_cnt;
struct foreign_sync foreign_syncs[FOREIGN_SYNCS_MAX]; struct foreign_sync foreign_syncs[FOREIGN_SYNCS_MAX];

View File

@ -56,6 +56,11 @@ extern u8 *doc_path; /* path to documentation dir */
u8 *find_binary(u8 *fname); u8 *find_binary(u8 *fname);
/* Parses the kill signal environment variable, FATALs on error.
If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */
int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal);
/* Read a bitmap from file fname to memory /* Read a bitmap from file fname to memory
This is for the -B option again. */ This is for the -B option again. */

View File

@ -80,11 +80,11 @@
/* Default timeout for fuzzed code (milliseconds). This is the upper bound, /* Default timeout for fuzzed code (milliseconds). This is the upper bound,
also used for detecting hangs; the actual value is auto-scaled: */ also used for detecting hangs; the actual value is auto-scaled: */
#define EXEC_TIMEOUT 1000 #define EXEC_TIMEOUT 1000U
/* Timeout rounding factor when auto-scaling (milliseconds): */ /* Timeout rounding factor when auto-scaling (milliseconds): */
#define EXEC_TM_ROUND 20 #define EXEC_TM_ROUND 20U
/* 64bit arch MACRO */ /* 64bit arch MACRO */
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) #if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
@ -93,48 +93,48 @@
/* Default memory limit for child process (MB) 0 = disabled : */ /* Default memory limit for child process (MB) 0 = disabled : */
#define MEM_LIMIT 0 #define MEM_LIMIT 0U
/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ /* Default memory limit when running in QEMU mode (MB) 0 = disabled : */
#define MEM_LIMIT_QEMU 0 #define MEM_LIMIT_QEMU 0U
/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ /* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */
#define MEM_LIMIT_UNICORN 0 #define MEM_LIMIT_UNICORN 0U
/* Number of calibration cycles per every new test case (and for test /* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */ cases that show variable behavior): */
#define CAL_CYCLES 8 #define CAL_CYCLES 8U
#define CAL_CYCLES_LONG 40 #define CAL_CYCLES_LONG 40U
/* Number of subsequent timeouts before abandoning an input file: */ /* Number of subsequent timeouts before abandoning an input file: */
#define TMOUT_LIMIT 250 #define TMOUT_LIMIT 250U
/* Maximum number of unique hangs or crashes to record: */ /* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500 #define KEEP_UNIQUE_HANG 500U
#define KEEP_UNIQUE_CRASH 5000 #define KEEP_UNIQUE_CRASH 5000U
/* Baseline number of random tweaks during a single 'havoc' stage: */ /* Baseline number of random tweaks during a single 'havoc' stage: */
#define HAVOC_CYCLES 256 #define HAVOC_CYCLES 256U
#define HAVOC_CYCLES_INIT 1024 #define HAVOC_CYCLES_INIT 1024U
/* Maximum multiplier for the above (should be a power of two, beware /* Maximum multiplier for the above (should be a power of two, beware
of 32-bit int overflows): */ of 32-bit int overflows): */
#define HAVOC_MAX_MULT 64 #define HAVOC_MAX_MULT 64U
#define HAVOC_MAX_MULT_MOPT 64 #define HAVOC_MAX_MULT_MOPT 64U
/* Absolute minimum number of havoc cycles (after all adjustments): */ /* Absolute minimum number of havoc cycles (after all adjustments): */
#define HAVOC_MIN 12 #define HAVOC_MIN 12U
/* Power Schedule Divisor */ /* Power Schedule Divisor */
#define POWER_BETA 1 #define POWER_BETA 1U
#define MAX_FACTOR (POWER_BETA * 32) #define MAX_FACTOR (POWER_BETA * 32)
/* Maximum stacking for havoc-stage tweaks. The actual value is calculated /* Maximum stacking for havoc-stage tweaks. The actual value is calculated
@ -146,19 +146,19 @@
In other words, the default (n = 4) produces 2, 4, 8, 16 In other words, the default (n = 4) produces 2, 4, 8, 16
stacked tweaks: */ stacked tweaks: */
#define HAVOC_STACK_POW2 4 #define HAVOC_STACK_POW2 4U
/* Caps on block sizes for cloning and deletion operations. Each of these /* Caps on block sizes for cloning and deletion operations. Each of these
ranges has a 33% probability of getting picked, except for the first ranges has a 33% probability of getting picked, except for the first
two cycles where smaller blocks are favored: */ two cycles where smaller blocks are favored: */
#define HAVOC_BLK_SMALL 32 #define HAVOC_BLK_SMALL 32U
#define HAVOC_BLK_MEDIUM 128 #define HAVOC_BLK_MEDIUM 128U
#define HAVOC_BLK_LARGE 1500 #define HAVOC_BLK_LARGE 1500U
/* Extra-large blocks, selected very rarely (<5% of the time): */ /* Extra-large blocks, selected very rarely (<5% of the time): */
#define HAVOC_BLK_XL 32768 #define HAVOC_BLK_XL 32768U
/* Probabilities of skipping non-favored entries in the queue, expressed as /* Probabilities of skipping non-favored entries in the queue, expressed as
percentages: */ percentages: */
@ -186,13 +186,15 @@
#define TRIM_START_STEPS 16 #define TRIM_START_STEPS 16
#define TRIM_END_STEPS 1024 #define TRIM_END_STEPS 1024
/* Maximum size of input file, in bytes (keep under 100MB): */ /* Maximum size of input file, in bytes (keep under 100MB, default 1MB):
(note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c
and afl-fuzz-state.c have to be changed as well! */
#define MAX_FILE (1 * 1024 * 1024) #define MAX_FILE (1 * 1024 * 1024U)
/* The same, for the test case minimizer: */ /* The same, for the test case minimizer: */
#define TMIN_MAX_FILE (10 * 1024 * 1024) #define TMIN_MAX_FILE (10 * 1024 * 1024U)
/* Block normalization steps for afl-tmin: */ /* Block normalization steps for afl-tmin: */
@ -380,7 +382,7 @@
after changing this - otherwise, SEGVs may ensue. */ after changing this - otherwise, SEGVs may ensue. */
#define MAP_SIZE_POW2 16 #define MAP_SIZE_POW2 16
#define MAP_SIZE (1 << MAP_SIZE_POW2) #define MAP_SIZE (1U << MAP_SIZE_POW2)
/* Maximum allocator request size (keep well under INT_MAX): */ /* Maximum allocator request size (keep well under INT_MAX): */

View File

@ -295,7 +295,7 @@ static inline const char *colorfilter(const char *x) {
\ \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \ "\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \ SAYF(cLRD "\n Location : " cRST "%s(), %s:%d\n\n", __func__, \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
exit(1); \ exit(1); \
\ \
@ -308,7 +308,7 @@ static inline const char *colorfilter(const char *x) {
\ \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \ "\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%d\n\n", __func__, \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
abort(); \ abort(); \
\ \
@ -322,7 +322,7 @@ static inline const char *colorfilter(const char *x) {
fflush(stdout); \ fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \ "\n[-] SYSTEM ERROR : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%d\n", __func__, \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
exit(1); \ exit(1); \

View File

@ -61,6 +61,7 @@ static char *afl_environment_variables[] = {
"AFL_IMPORT_FIRST", "AFL_IMPORT_FIRST",
"AFL_INST_LIBS", "AFL_INST_LIBS",
"AFL_INST_RATIO", "AFL_INST_RATIO",
"AFL_KILL_SIGNAL",
"AFL_KEEP_TRACES", "AFL_KEEP_TRACES",
"AFL_KEEP_ASSEMBLY", "AFL_KEEP_ASSEMBLY",
"AFL_LD_HARD_FAIL", "AFL_LD_HARD_FAIL",

View File

@ -99,6 +99,8 @@ typedef struct afl_forkserver {
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len); void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
u8 kill_signal;
} afl_forkserver_t; } afl_forkserver_t;
typedef enum fsrv_run_result { typedef enum fsrv_run_result {

View File

@ -50,7 +50,7 @@ typedef uint32_t u32;
#define FS_OPT_SHDMEM_FUZZ 0x01000000 #define FS_OPT_SHDMEM_FUZZ 0x01000000
#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 #define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 // FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1) #define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
#define FS_OPT_SET_MAPSIZE(x) \ #define FS_OPT_SET_MAPSIZE(x) \
(x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1))

View File

@ -200,7 +200,7 @@ struct InsTrim : public ModulePass {
LoadInst * PrevCtx = NULL; // for CTX sensitive coverage LoadInst * PrevCtx = NULL; // for CTX sensitive coverage
if (ctx_str) if (ctx_str)
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLContext = new GlobalVariable( AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx"); M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
#else #else
@ -211,7 +211,7 @@ struct InsTrim : public ModulePass {
#ifdef AFL_HAVE_VECTOR_INTRINSICS #ifdef AFL_HAVE_VECTOR_INTRINSICS
if (ngram_size) if (ngram_size)
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
/* Initializer */ nullptr, "__afl_prev_loc"); /* Initializer */ nullptr, "__afl_prev_loc");
@ -224,7 +224,7 @@ struct InsTrim : public ModulePass {
#endif #endif
else else
#endif #endif
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
#else #else
@ -407,10 +407,10 @@ struct InsTrim : public ModulePass {
// does the function have calls? and is any of the calls larger than // does the function have calls? and is any of the calls larger than
// one basic block? // one basic block?
has_calls = 0; has_calls = 0;
for (auto &BB : F) { for (auto &BB2 : F) {
if (has_calls) break; if (has_calls) break;
for (auto &IN : BB) { for (auto &IN : BB2) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
@ -454,7 +454,7 @@ struct InsTrim : public ModulePass {
auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin()); auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
DenseMap<BasicBlock *, unsigned> PredMap; DenseMap<BasicBlock *, unsigned> PredMap;
for (auto PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) { for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
BasicBlock *PBB = *PI; BasicBlock *PBB = *PI;
auto It = PredMap.insert({PBB, genLabel()}); auto It = PredMap.insert({PBB, genLabel()});
@ -568,7 +568,7 @@ struct InsTrim : public ModulePass {
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr, OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
total_rs, total_hs, modeline); total_rs, total_hs, modeline);
} }

View File

@ -332,11 +332,11 @@ bool Indistinguish(uint32_t node1, uint32_t node2) {
void MakeUniq(uint32_t now) { void MakeUniq(uint32_t now) {
bool StopFlag = false;
if (Marked.find(now) == Marked.end()) { if (Marked.find(now) == Marked.end()) {
for (uint32_t pred1 : t_Pred[now]) { for (uint32_t pred1 : t_Pred[now]) {
bool StopFlag = false;
for (uint32_t pred2 : t_Pred[now]) { for (uint32_t pred2 : t_Pred[now]) {
if (pred1 == pred2) continue; if (pred1 == pred2) continue;

View File

@ -1,8 +1,9 @@
# Using afl++ with partial instrumentation # Using afl++ with partial instrumentation
This file describes how to selectively instrument only source files This file describes two different mechanisms to selectively instrument
or functions that are of interest to you using the LLVM and GCC_PLUGIN only specific parts in the target.
instrumentation provided by afl++.
Both mechanisms work for LLVM and GCC_PLUGIN, but not for afl-clang/afl-gcc.
## 1) Description and purpose ## 1) Description and purpose
@ -12,28 +13,42 @@ the program, leaving the rest uninstrumented. This helps to focus the fuzzer
on the important parts of the program, avoiding undesired noise and on the important parts of the program, avoiding undesired noise and
disturbance by uninteresting code being exercised. disturbance by uninteresting code being exercised.
For this purpose, a "partial instrumentation" support en par with llvm sancov For this purpose, "partial instrumentation" support is provided by afl++ that
is provided by afl++ that allows to specify on a source file and function allows to specify what should be instrumented and what not.
level which function should be compiled with or without instrumentation.
Note: When using PCGUARD mode - and llvm 12+ - you can use this instead: Both mechanisms can be used together.
https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
The llvm sancov list format is fully supported by afl++, however afl++ has ## 2) Selective instrumentation with __AFL_COVERAGE_... directives
more flexibility.
## 2a) Building the LLVM module In this mechanism the selective instrumentation is done in the source code.
The new code is part of the existing afl++ LLVM module in the instrumentation/ After the includes a special define has to be made, eg.:
subdirectory. There is nothing specifically to do for the build :)
## 2b) Building the GCC module ```
#include <stdio.h>
#include <stdint.h>
// ...
__AFL_COVERAGE(); // <- required for this feature to work
```
The new code is part of the existing afl++ GCC_PLUGIN module in the If you want to disable the coverage at startup until you specify coverage
instrumentation/ subdirectory. There is nothing specifically to do for should be started, then add `__AFL_COVERAGE_START_OFF();` at that position.
the build :)
## 3) How to use the partial instrumentation mode From here on out you have the following macros available that you can use
in any function where you want:
* `__AFL_COVERAGE_ON();` - enable coverage from this point onwards
* `__AFL_COVERAGE_OFF();` - disable coverage from this point onwards
* `__AFL_COVERAGE_DISCARD();` - reset all coverage gathered until this point
* `__AFL_COVERAGE_ABORT();` - mark this test case as unimportant. Whatever happens, afl-fuzz will ignore it.
## 3) Selective instrumenation with AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST
This feature is equivalent to llvm 12 sancov feature and allows to specify
on a filename and/or function name level to instrument these or skip them.
### 3a) How to use the partial instrumentation mode
In order to build with partial instrumentation, you need to build with In order to build with partial instrumentation, you need to build with
afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++. afl-clang-fast/afl-clang-fast++ or afl-clang-lto/afl-clang-lto++.
@ -90,7 +105,7 @@ fun: MallocFoo
``` ```
Note that whitespace is ignored and comments (`# foo`) are supported. Note that whitespace is ignored and comments (`# foo`) are supported.
## 4) UNIX-style pattern matching ### 3b) UNIX-style pattern matching
You can add UNIX-style pattern matching in the "instrument file list" entries. You can add UNIX-style pattern matching in the "instrument file list" entries.
See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags. See `man fnmatch` for the syntax. We do not set any of the `fnmatch` flags.

View File

@ -1403,24 +1403,17 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock(); bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc;
if (IsEntryBB) { if (IsEntryBB) {
if (auto SP = F.getSubprogram())
EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even // Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before // if we aren't splitting the block, it's nice for allocas to be before
// calls. // calls.
IP = PrepareToSplitEntryBlock(BB, IP); IP = PrepareToSplitEntryBlock(BB, IP);
} else {
EntryLoc = IP->getDebugLoc();
} }
IRBuilder<> IRB(&*IP); IRBuilder<> IRB(&*IP);
IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePC) { if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC) IRB.CreateCall(SanCovTracePC)

View File

@ -1163,24 +1163,18 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock(); bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc;
if (IsEntryBB) { if (IsEntryBB) {
if (auto SP = F.getSubprogram())
EntryLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
// Keep static allocas and llvm.localescape calls in the entry block. Even // Keep static allocas and llvm.localescape calls in the entry block. Even
// if we aren't splitting the block, it's nice for allocas to be before // if we aren't splitting the block, it's nice for allocas to be before
// calls. // calls.
IP = PrepareToSplitEntryBlock(BB, IP); IP = PrepareToSplitEntryBlock(BB, IP);
} else {
EntryLoc = IP->getDebugLoc();
} }
IRBuilder<> IRB(&*IP); IRBuilder<> IRB(&*IP);
IRB.SetCurrentDebugLocation(EntryLoc);
if (Options.TracePC) { if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC); IRB.CreateCall(SanCovTracePC);

View File

@ -76,7 +76,9 @@
#endif #endif
u8 __afl_area_initial[MAP_INITIAL_SIZE]; u8 __afl_area_initial[MAP_INITIAL_SIZE];
u8 * __afl_area_ptr_dummy = __afl_area_initial;
u8 * __afl_area_ptr = __afl_area_initial; u8 * __afl_area_ptr = __afl_area_initial;
u8 * __afl_area_ptr_backup = __afl_area_initial;
u8 * __afl_dictionary; u8 * __afl_dictionary;
u8 * __afl_fuzz_ptr; u8 * __afl_fuzz_ptr;
u32 __afl_fuzz_len_dummy; u32 __afl_fuzz_len_dummy;
@ -87,7 +89,12 @@ u32 __afl_map_size = MAP_SIZE;
u32 __afl_dictionary_len; u32 __afl_dictionary_len;
u64 __afl_map_addr; u64 __afl_map_addr;
#ifdef __ANDROID__ // for the __AFL_COVERAGE_ON/__AFL_COVERAGE_OFF features to work:
int __afl_selective_coverage __attribute__((weak));
int __afl_selective_coverage_start_off __attribute__((weak));
int __afl_selective_coverage_temp = 1;
#if defined(__ANDROID__) || defined(__HAIKU__)
PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX];
u32 __afl_prev_ctx; u32 __afl_prev_ctx;
u32 __afl_cmp_counter; u32 __afl_cmp_counter;
@ -100,6 +107,7 @@ __thread u32 __afl_cmp_counter;
int __afl_sharedmem_fuzzing __attribute__((weak)); int __afl_sharedmem_fuzzing __attribute__((weak));
struct cmp_map *__afl_cmp_map; struct cmp_map *__afl_cmp_map;
struct cmp_map *__afl_cmp_map_backup;
/* Child pid? */ /* Child pid? */
@ -230,7 +238,7 @@ static void __afl_map_shm_fuzz() {
static void __afl_map_shm(void) { static void __afl_map_shm(void) {
// if we are not running in afl ensure the map exists // if we are not running in afl ensure the map exists
if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; } if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_ptr_dummy; }
char *id_str = getenv(SHM_ENV_VAR); char *id_str = getenv(SHM_ENV_VAR);
@ -295,11 +303,17 @@ static void __afl_map_shm(void) {
if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) { if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
if (__afl_map_addr) if (__afl_map_addr) {
munmap((void *)__afl_map_addr, __afl_final_loc); munmap((void *)__afl_map_addr, __afl_final_loc);
else
} else {
free(__afl_area_ptr); free(__afl_area_ptr);
__afl_area_ptr = __afl_area_initial;
}
__afl_area_ptr = __afl_area_ptr_dummy;
} }
@ -396,9 +410,42 @@ static void __afl_map_shm(void) {
free(__afl_area_ptr); free(__afl_area_ptr);
__afl_area_ptr = NULL; __afl_area_ptr = NULL;
if (__afl_final_loc > MAP_INITIAL_SIZE)
if (__afl_final_loc > MAP_INITIAL_SIZE) {
__afl_area_ptr = malloc(__afl_final_loc); __afl_area_ptr = malloc(__afl_final_loc);
if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
}
if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_ptr_dummy; }
}
__afl_area_ptr_backup = __afl_area_ptr;
if (__afl_selective_coverage) {
if (__afl_map_size > MAP_INITIAL_SIZE) {
__afl_area_ptr_dummy = malloc(__afl_map_size);
if (__afl_area_ptr_dummy) {
if (__afl_selective_coverage_start_off) {
__afl_area_ptr = __afl_area_ptr_dummy;
}
} else {
fprintf(stderr, "Error: __afl_selective_coverage failed!\n");
__afl_selective_coverage = 0;
// continue;
}
}
} }
@ -449,6 +496,8 @@ static void __afl_map_shm(void) {
__afl_cmp_map = shmat(shm_id, NULL, 0); __afl_cmp_map = shmat(shm_id, NULL, 0);
#endif #endif
__afl_cmp_map_backup = __afl_cmp_map;
if (!__afl_cmp_map || __afl_cmp_map == (void *)-1) { if (!__afl_cmp_map || __afl_cmp_map == (void *)-1) {
perror("shmat for cmplog"); perror("shmat for cmplog");
@ -683,7 +732,7 @@ static void __afl_start_forkserver(void) {
#endif #endif
u8 tmp[4] = {0, 0, 0, 0}; u8 tmp[4] = {0, 0, 0, 0};
u32 status = 0; u32 status_for_fsrv = 0;
u32 already_read_first = 0; u32 already_read_first = 0;
u32 was_killed; u32 was_killed;
@ -691,17 +740,26 @@ static void __afl_start_forkserver(void) {
void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL); void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL);
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) {
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT; status_for_fsrv |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
if (status) status |= (FS_OPT_ENABLED); }
memcpy(tmp, &status, 4);
if (__afl_dictionary_len && __afl_dictionary) {
status_for_fsrv |= FS_OPT_AUTODICT;
}
if (__afl_sharedmem_fuzzing != 0) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
if (status_for_fsrv) { status_for_fsrv |= (FS_OPT_ENABLED); }
memcpy(tmp, &status_for_fsrv, 4);
/* Phone home and tell the parent that we're OK. If parent isn't there, /* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */ assume we're not running in forkserver mode and just execute program. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) { if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
@ -726,7 +784,6 @@ static void __afl_start_forkserver(void) {
// great lets pass the dictionary through the forkserver FD // great lets pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0; u32 len = __afl_dictionary_len, offset = 0;
s32 ret;
if (write(FORKSRV_FD + 1, &len, 4) != 4) { if (write(FORKSRV_FD + 1, &len, 4) != 4) {
@ -738,6 +795,7 @@ static void __afl_start_forkserver(void) {
while (len != 0) { while (len != 0) {
s32 ret;
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
if (ret < 1) { if (ret < 1) {
@ -894,6 +952,8 @@ int __afl_persistent_loop(unsigned int max_cnt) {
cycle_cnt = max_cnt; cycle_cnt = max_cnt;
first_pass = 0; first_pass = 0;
__afl_selective_coverage_temp = 1;
return 1; return 1;
} }
@ -906,6 +966,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
__afl_area_ptr[0] = 1; __afl_area_ptr[0] = 1;
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T)); memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
__afl_selective_coverage_temp = 1;
return 1; return 1;
@ -915,7 +976,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
follows the loop is not traced. We do that by pivoting back to the follows the loop is not traced. We do that by pivoting back to the
dummy output region. */ dummy output region. */
__afl_area_ptr = __afl_area_initial; __afl_area_ptr = __afl_area_ptr_dummy;
} }
@ -937,7 +998,7 @@ void __afl_manual_init(void) {
init_done = 1; init_done = 1;
is_persistent = 0; is_persistent = 0;
__afl_sharedmem_fuzzing = 0; __afl_sharedmem_fuzzing = 0;
if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial; if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_ptr_dummy;
if (getenv("AFL_DEBUG")) if (getenv("AFL_DEBUG"))
fprintf(stderr, fprintf(stderr,
@ -998,7 +1059,12 @@ __attribute__((constructor(1))) void __afl_auto_second(void) {
else else
ptr = (u8 *)malloc(__afl_final_loc); ptr = (u8 *)malloc(__afl_final_loc);
if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr; if (ptr && (ssize_t)ptr != -1) {
__afl_area_ptr = ptr;
__afl_area_ptr_backup = __afl_area_ptr;
}
} }
@ -1014,7 +1080,12 @@ __attribute__((constructor(0))) void __afl_auto_first(void) {
ptr = (u8 *)malloc(1024000); ptr = (u8 *)malloc(1024000);
if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr; if (ptr && (ssize_t)ptr != -1) {
__afl_area_ptr = ptr;
__afl_area_ptr_backup = __afl_area_ptr;
}
} }
@ -1304,3 +1375,69 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
} }
/* COVERAGE manipulation features */
// this variable is then used in the shm setup to create an additional map
// if __afl_map_size > MAP_SIZE or cmplog is used.
// Especially with cmplog this would result in a ~260MB mem increase per
// target run.
// disable coverage from this point onwards until turned on again
void __afl_coverage_off() {
if (likely(__afl_selective_coverage)) {
__afl_area_ptr = __afl_area_ptr_dummy;
__afl_cmp_map = NULL;
}
}
// enable coverage
void __afl_coverage_on() {
if (likely(__afl_selective_coverage && __afl_selective_coverage_temp)) {
__afl_area_ptr = __afl_area_ptr_backup;
__afl_cmp_map = __afl_cmp_map_backup;
}
}
// discard all coverage up to this point
void __afl_coverage_discard() {
memset(__afl_area_ptr_backup, 0, __afl_map_size);
__afl_area_ptr_backup[0] = 1;
if (__afl_cmp_map) { memset(__afl_cmp_map, 0, sizeof(struct cmp_map)); }
}
// discard the testcase
void __afl_coverage_abort() {
__afl_coverage_discard();
if (likely(is_persistent && __afl_selective_coverage)) {
__afl_coverage_off();
__afl_selective_coverage_temp = 0;
} else {
exit(0);
}
}
// mark this area as especially interesting
void __afl_coverage_interesting(u8 val, u32 id) {
__afl_area_ptr[id] = val;
}

View File

@ -228,7 +228,7 @@ struct afl_pass : gimple_opt_pass {
const bool neverZero; const bool neverZero;
/* Count instrumented blocks. */ /* Count instrumented blocks. */
int inst_blocks; unsigned int inst_blocks;
virtual unsigned int execute(function *fn) { virtual unsigned int execute(function *fn) {
@ -444,8 +444,10 @@ struct afl_pass : gimple_opt_pass {
DECL_EXTERNAL(decl) = 1; DECL_EXTERNAL(decl) = 1;
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
TREE_STATIC(decl) = 1; TREE_STATIC(decl) = 1;
#if !defined(__ANDROID__) && !defined(__HAIKU__)
set_decl_tls_model( set_decl_tls_model(
decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC)); decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC));
#endif
return decl; return decl;
} }
@ -920,8 +922,9 @@ int plugin_init(struct plugin_name_args * info,
struct plugin_gcc_version *version) { struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version)) if (!plugin_default_version_check(version, &gcc_version))
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"), FATAL(G_("GCC and plugin have incompatible versions, expected GCC %s, "
GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR); "is %s"),
gcc_version.basever, version->basever);
/* Show a banner. */ /* Show a banner. */
bool quiet = false; bool quiet = false;
@ -931,7 +934,7 @@ int plugin_init(struct plugin_name_args * info,
quiet = true; quiet = true;
/* Decide instrumentation ratio. */ /* Decide instrumentation ratio. */
int inst_ratio = 100; unsigned int inst_ratio = 100U;
if (char *inst_ratio_str = getenv("AFL_INST_RATIO")) if (char *inst_ratio_str = getenv("AFL_INST_RATIO"))
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio || if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
inst_ratio > 100) inst_ratio > 100)

View File

@ -355,7 +355,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1); *Str2P = callInst->getArgOperand(1);
std::string Str1, Str2; std::string Str1, Str2;
StringRef TmpStr; StringRef TmpStr;
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr); bool HasStr1;
getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr1 = false; HasStr1 = false;
@ -367,7 +368,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
} }
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr); bool HasStr2;
getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr2 = false; HasStr2 = false;

View File

@ -70,7 +70,7 @@ class AFLLTOPass : public ModulePass {
if (getenv("AFL_DEBUG")) debug = 1; if (getenv("AFL_DEBUG")) debug = 1;
if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL) if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
if ((afl_global_id = atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE) if ((afl_global_id = atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE)
FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %d\n", FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %u\n",
ptr, MAP_SIZE - 1); ptr, MAP_SIZE - 1);
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
@ -100,9 +100,9 @@ class AFLLTOPass : public ModulePass {
bool AFLLTOPass::runOnModule(Module &M) { bool AFLLTOPass::runOnModule(Module &M) {
LLVMContext & C = M.getContext(); LLVMContext & C = M.getContext();
std::vector<std::string> dictionary; std::vector<std::string> dictionary;
std::vector<CallInst *> calls; // std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap; DenseMap<Value *, std::string *> valueMap;
std::vector<BasicBlock *> BlockList; std::vector<BasicBlock *> BlockList;
char * ptr; char * ptr;
@ -471,7 +471,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
*Str2P = callInst->getArgOperand(1); *Str2P = callInst->getArgOperand(1);
std::string Str1, Str2; std::string Str1, Str2;
StringRef TmpStr; StringRef TmpStr;
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr); bool HasStr1;
getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr1 = false; HasStr1 = false;
@ -483,7 +484,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
} }
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr); bool HasStr2;
getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty()) { if (TmpStr.empty()) {
HasStr2 = false; HasStr2 = false;
@ -671,7 +673,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (!be_quiet) { if (!be_quiet) {
std::string outstring;
fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen, fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
thestring.length()); thestring.length());
for (uint8_t i = 0; i < thestring.length(); i++) { for (uint8_t i = 0; i < thestring.length(); i++) {
@ -799,7 +800,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (documentFile) { if (documentFile) {
fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n", fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%d\n",
moduleID, F.getName().str().c_str(), afl_global_id); moduleID, F.getName().str().c_str(), afl_global_id);
} }
@ -871,10 +872,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
while ((map = map >> 1)) while ((map = map >> 1))
pow2map++; pow2map++;
WARNF( WARNF(
"We have %u blocks to instrument but the map size is only %u. Either " "We have %d blocks to instrument but the map size is only %u. Either "
"edit config.h and set MAP_SIZE_POW2 from %u to %u, then recompile " "edit config.h and set MAP_SIZE_POW2 from %d to %u, then recompile "
"afl-fuzz and llvm_mode and then make this target - or set " "afl-fuzz and llvm_mode and then make this target - or set "
"AFL_MAP_SIZE with at least size %u when running afl-fuzz with this " "AFL_MAP_SIZE with at least size %d when running afl-fuzz with this "
"target.", "target.",
afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id); afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id);
@ -937,8 +938,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (dictionary.size()) { if (dictionary.size()) {
size_t memlen = 0, count = 0, offset = 0; size_t memlen = 0, count = 0;
char * ptr;
// sort and unique the dictionary // sort and unique the dictionary
std::sort(dictionary.begin(), dictionary.end()); std::sort(dictionary.begin(), dictionary.end());
@ -953,14 +953,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
} }
if (!be_quiet) if (!be_quiet)
printf("AUTODICTIONARY: %lu string%s found\n", count, printf("AUTODICTIONARY: %zu string%s found\n", count,
count == 1 ? "" : "s"); count == 1 ? "" : "s");
if (count) { if (count) {
if ((ptr = (char *)malloc(memlen + count)) == NULL) { if ((ptr = (char *)malloc(memlen + count)) == NULL) {
fprintf(stderr, "Error: malloc for %lu bytes failed!\n", fprintf(stderr, "Error: malloc for %zu bytes failed!\n",
memlen + count); memlen + count);
exit(-1); exit(-1);
@ -968,6 +968,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
count = 0; count = 0;
size_t offset = 0;
for (auto token : dictionary) { for (auto token : dictionary) {
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) { if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
@ -1031,7 +1032,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations with no collisions (on average %llu " OKF("Instrumented %d locations with no collisions (on average %llu "
"collisions would be in afl-gcc/afl-clang-fast) (%s mode).", "collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
inst_blocks, calculateCollisions(inst_blocks), modeline); inst_blocks, calculateCollisions(inst_blocks), modeline);

View File

@ -241,7 +241,7 @@ bool AFLCoverage::runOnModule(Module &M) {
GlobalVariable *AFLContext = NULL; GlobalVariable *AFLContext = NULL;
if (ctx_str) if (ctx_str)
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLContext = new GlobalVariable( AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx"); M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
#else #else
@ -252,7 +252,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#ifdef AFL_HAVE_VECTOR_INTRINSICS #ifdef AFL_HAVE_VECTOR_INTRINSICS
if (ngram_size) if (ngram_size)
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage, M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
/* Initializer */ nullptr, "__afl_prev_loc"); /* Initializer */ nullptr, "__afl_prev_loc");
@ -265,7 +265,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#endif #endif
else else
#endif #endif
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__HAIKU__)
AFLPrevLoc = new GlobalVariable( AFLPrevLoc = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc"); M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
#else #else
@ -327,10 +327,10 @@ bool AFLCoverage::runOnModule(Module &M) {
// does the function have calls? and is any of the calls larger than one // does the function have calls? and is any of the calls larger than one
// basic block? // basic block?
for (auto &BB : F) { for (auto &BB_2 : F) {
if (has_calls) break; if (has_calls) break;
for (auto &IN : BB) { for (auto &IN : BB_2) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
@ -628,7 +628,7 @@ bool AFLCoverage::runOnModule(Module &M) {
getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations (%s mode, ratio %u%%).", inst_blocks, OKF("Instrumented %d locations (%s mode, ratio %u%%).", inst_blocks,
modeline, inst_ratio); modeline, inst_ratio);
} }

View File

@ -186,16 +186,19 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
selectcmpInst->getPredicate() == CmpInst::ICMP_UGE || selectcmpInst->getPredicate() == CmpInst::ICMP_UGE ||
selectcmpInst->getPredicate() == CmpInst::ICMP_SGE || selectcmpInst->getPredicate() == CmpInst::ICMP_SGE ||
selectcmpInst->getPredicate() == CmpInst::ICMP_ULE || selectcmpInst->getPredicate() == CmpInst::ICMP_ULE ||
selectcmpInst->getPredicate() == CmpInst::ICMP_SLE) { selectcmpInst->getPredicate() == CmpInst::ICMP_SLE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
auto op0 = selectcmpInst->getOperand(0); selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
auto op1 = selectcmpInst->getOperand(1); selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE ||
IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType()); selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLT ||
/* this is probably not needed but we do it anyway */ selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
if (!intTyOp0 || !intTyOp1) { continue; } selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE) {
icomps.push_back(selectcmpInst); icomps.push_back(selectcmpInst);
@ -221,16 +224,66 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
auto op0 = selectcmpInst->getOperand(0); auto op0 = selectcmpInst->getOperand(0);
auto op1 = selectcmpInst->getOperand(1); auto op1 = selectcmpInst->getOperand(1);
IntegerType *intTyOp0 = dyn_cast<IntegerType>(op0->getType()); IntegerType * intTyOp0 = NULL;
IntegerType *intTyOp1 = dyn_cast<IntegerType>(op1->getType()); IntegerType * intTyOp1 = NULL;
unsigned max_size = 0;
unsigned max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
? intTyOp0->getBitWidth()
: intTyOp1->getBitWidth();
std::vector<Value *> args; std::vector<Value *> args;
args.push_back(op0);
args.push_back(op1); if (selectcmpInst->getOpcode() == Instruction::FCmp) {
auto ty0 = op0->getType();
if (ty0->isHalfTy()
#if LLVM_VERSION_MAJOR >= 11
|| ty0->isBFloatTy()
#endif
)
max_size = 16;
else if (ty0->isFloatTy())
max_size = 32;
else if (ty0->isDoubleTy())
max_size = 64;
if (max_size) {
Value *V0 = IRB.CreateBitCast(op0, IntegerType::get(C, max_size));
intTyOp0 = dyn_cast<IntegerType>(V0->getType());
Value *V1 = IRB.CreateBitCast(op1, IntegerType::get(C, max_size));
intTyOp1 = dyn_cast<IntegerType>(V1->getType());
if (intTyOp0 && intTyOp1) {
max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
? intTyOp0->getBitWidth()
: intTyOp1->getBitWidth();
args.push_back(V0);
args.push_back(V1);
} else {
max_size = 0;
}
}
} else {
intTyOp0 = dyn_cast<IntegerType>(op0->getType());
intTyOp1 = dyn_cast<IntegerType>(op1->getType());
if (intTyOp0 && intTyOp1) {
max_size = intTyOp0->getBitWidth() > intTyOp1->getBitWidth()
? intTyOp0->getBitWidth()
: intTyOp1->getBitWidth();
args.push_back(op0);
args.push_back(op1);
}
}
if (max_size < 8 || max_size > 64 || !intTyOp0 || !intTyOp1) continue;
switch (max_size) { switch (max_size) {

View File

@ -68,7 +68,7 @@ class CompareTransform : public ModulePass {
const char *getPassName() const override { const char *getPassName() const override {
#else #else
StringRef getPassName() const override { StringRef getPassName() const override {
#endif #endif
return "transforms compare functions"; return "transforms compare functions";
@ -101,21 +101,30 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
IntegerType * Int64Ty = IntegerType::getInt64Ty(C); IntegerType * Int64Ty = IntegerType::getInt64Ty(C);
#if LLVM_VERSION_MAJOR < 9 #if LLVM_VERSION_MAJOR < 9
Constant * Function *tolowerFn;
#else #else
FunctionCallee FunctionCallee tolowerFn;
#endif #endif
c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty {
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9 #if LLVM_VERSION_MAJOR < 9
Function *tolowerFn = cast<Function>(c); Constant *
#else #else
FunctionCallee tolowerFn = c; FunctionCallee
#endif #endif
c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty
#if LLVM_VERSION_MAJOR < 5
,
NULL
#endif
);
#if LLVM_VERSION_MAJOR < 9
tolowerFn = cast<Function>(c);
#else
tolowerFn = c;
#endif
}
/* iterate over all functions, bbs and instruction and add suitable calls to /* iterate over all functions, bbs and instruction and add suitable calls to
* strcmp/memcmp/strncmp/strcasecmp/strncasecmp */ * strcmp/memcmp/strncmp/strcasecmp/strncasecmp */
@ -234,7 +243,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (!HasStr2) { if (!HasStr2) {
auto *Ptr = dyn_cast<ConstantExpr>(Str1P); Ptr = dyn_cast<ConstantExpr>(Str1P);
if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) { if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {

View File

@ -53,7 +53,7 @@ class SplitComparesTransform : public ModulePass {
public: public:
static char ID; static char ID;
SplitComparesTransform() : ModulePass(ID) { SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) {
initInstrumentList(); initInstrumentList();
@ -555,6 +555,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) { if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ || if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UEQ ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE || selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE || selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGT || selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
@ -735,6 +736,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
BasicBlock * signequal2_bb = signequal_bb; BasicBlock * signequal2_bb = signequal_bb;
switch (FcmpInst->getPredicate()) { switch (FcmpInst->getPredicate()) {
case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OEQ:
icmp_exponent_result = icmp_exponent_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, m_e0, m_e1);
@ -816,6 +818,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
switch (FcmpInst->getPredicate()) { switch (FcmpInst->getPredicate()) {
case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OEQ:
/* if the exponents are satifying the compare do a fraction cmp in /* if the exponents are satifying the compare do a fraction cmp in
* middle_bb */ * middle_bb */
@ -900,11 +903,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
/* compare the fractions of the operands */ /* compare the fractions of the operands */
Instruction *icmp_fraction_result; Instruction *icmp_fraction_result;
Instruction *icmp_fraction_result2;
BasicBlock * middle2_bb = middle_bb; BasicBlock * middle2_bb = middle_bb;
PHINode * PN2 = nullptr; PHINode * PN2 = nullptr;
switch (FcmpInst->getPredicate()) { switch (FcmpInst->getPredicate()) {
case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OEQ:
icmp_fraction_result = icmp_fraction_result =
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1); CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_f0, t_f1);
@ -927,6 +930,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
case CmpInst::FCMP_OLT: case CmpInst::FCMP_OLT:
case CmpInst::FCMP_ULT: { case CmpInst::FCMP_ULT: {
Instruction *icmp_fraction_result2;
middle2_bb = middle_bb->splitBasicBlock( middle2_bb = middle_bb->splitBasicBlock(
BasicBlock::iterator(middle_bb->getTerminator())); BasicBlock::iterator(middle_bb->getTerminator()));
@ -980,6 +985,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
switch (FcmpInst->getPredicate()) { switch (FcmpInst->getPredicate()) {
case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OEQ:
/* unequal signs cannot be equal values */ /* unequal signs cannot be equal values */
/* goto false branch */ /* goto false branch */

View File

@ -1 +1 @@
d66c9e2654 5400ce883a

View File

@ -903,8 +903,8 @@ static void usage(u8 *argv0) {
"Execution control settings:\n" "Execution control settings:\n"
" -f file - input file read by the tested program (stdin)\n" " -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%d ms)\n" " -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%d MB)\n" " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n" " -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine " " -W - use qemu-based instrumentation with Wine (Wine "

View File

@ -120,8 +120,13 @@ char compiler_mode_string[7][12] = {
u8 *getthecwd() { u8 *getthecwd() {
static u8 fail[] = ""; if (getcwd(cwd, sizeof(cwd)) == NULL) {
if (getcwd(cwd, sizeof(cwd)) == NULL) return fail;
static u8 fail[] = "";
return fail;
}
return cwd; return cwd;
} }
@ -654,9 +659,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
u32 idx;
if (lto_mode && argc > 1) { if (lto_mode && argc > 1) {
u32 idx;
for (idx = 1; idx < argc; idx++) { for (idx = 1; idx < argc; idx++) {
if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
@ -787,8 +792,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
#if defined(USEMMAP) && !defined(__HAIKU__) #if defined(USEMMAP)
#if !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt"; cc_params[cc_par_cnt++] = "-lrt";
#endif
#endif #endif
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
@ -822,6 +829,35 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"extern unsigned char *__afl_fuzz_ptr;" "extern unsigned char *__afl_fuzz_ptr;"
"unsigned char __afl_fuzz_alt[1048576];" "unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
if (plusplus_mode) {
cc_params[cc_par_cnt++] =
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"extern \"C\" void __afl_coverage_discard();"
"extern \"C\" void __afl_coverage_abort();"
"extern \"C\" void __afl_coverage_on();"
"extern \"C\" void __afl_coverage_off();";
} else {
cc_params[cc_par_cnt++] =
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
"void __afl_coverage_discard();"
"void __afl_coverage_abort();"
"void __afl_coverage_on();"
"void __afl_coverage_off();";
}
cc_params[cc_par_cnt++] =
"-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = "
"1;";
cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()";
cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()";
cc_params[cc_par_cnt++] =
"-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()";
cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ABORT()=__afl_coverage_abort()";
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
"-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : "
"__afl_fuzz_alt_ptr)"; "__afl_fuzz_alt_ptr)";
@ -931,8 +967,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif #endif
#ifdef USEMMAP #if defined(USEMMAP)
#if !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt"; cc_params[cc_par_cnt++] = "-lrt";
#endif
#endif #endif
} }
@ -1208,12 +1246,12 @@ int main(int argc, char **argv, char **envp) {
if (getenv("AFL_LLVM_INSTRUMENT")) { if (getenv("AFL_LLVM_INSTRUMENT")) {
u8 *ptr = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;");
while (ptr) { while (ptr2) {
if (strncasecmp(ptr, "afl", strlen("afl")) == 0 || if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 ||
strncasecmp(ptr, "classic", strlen("classic")) == 0) { strncasecmp(ptr2, "classic", strlen("classic")) == 0) {
if (instrument_mode == INSTRUMENT_LTO) { if (instrument_mode == INSTRUMENT_LTO) {
@ -1229,8 +1267,8 @@ int main(int argc, char **argv, char **envp) {
} }
if (strncasecmp(ptr, "pc-guard", strlen("pc-guard")) == 0 || if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
strncasecmp(ptr, "pcguard", strlen("pcguard")) == 0) { strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD)
instrument_mode = INSTRUMENT_PCGUARD; instrument_mode = INSTRUMENT_PCGUARD;
@ -1241,8 +1279,8 @@ int main(int argc, char **argv, char **envp) {
} }
// this is a hidden option // this is a hidden option
if (strncasecmp(ptr, "llvmnative", strlen("llvmnative")) == 0 || if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 ||
strncasecmp(ptr, "llvm-native", strlen("llvm-native")) == 0) { strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE)
instrument_mode = INSTRUMENT_LLVMNATIVE; instrument_mode = INSTRUMENT_LLVMNATIVE;
@ -1252,8 +1290,8 @@ int main(int argc, char **argv, char **envp) {
} }
if (strncasecmp(ptr, "cfg", strlen("cfg")) == 0 || if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
strncasecmp(ptr, "instrim", strlen("instrim")) == 0) { strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
if (instrument_mode == INSTRUMENT_LTO) { if (instrument_mode == INSTRUMENT_LTO) {
@ -1269,7 +1307,7 @@ int main(int argc, char **argv, char **envp) {
} }
if (strncasecmp(ptr, "lto", strlen("lto")) == 0) { if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) {
lto_mode = 1; lto_mode = 1;
if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) if (!instrument_mode || instrument_mode == INSTRUMENT_LTO)
@ -1280,7 +1318,7 @@ int main(int argc, char **argv, char **envp) {
} }
if (strcasecmp(ptr, "gcc") == 0) { if (strcasecmp(ptr2, "gcc") == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) if (!instrument_mode || instrument_mode == INSTRUMENT_GCC)
instrument_mode = INSTRUMENT_GCC; instrument_mode = INSTRUMENT_GCC;
@ -1291,7 +1329,7 @@ int main(int argc, char **argv, char **envp) {
} }
if (strcasecmp(ptr, "clang") == 0) { if (strcasecmp(ptr2, "clang") == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG)
instrument_mode = INSTRUMENT_CLANG; instrument_mode = INSTRUMENT_CLANG;
@ -1302,29 +1340,29 @@ int main(int argc, char **argv, char **envp) {
} }
if (strncasecmp(ptr, "ctx", strlen("ctx")) == 0) { if (strncasecmp(ptr2, "ctx", strlen("ctx")) == 0) {
instrument_opt_mode |= INSTRUMENT_OPT_CTX; instrument_opt_mode |= INSTRUMENT_OPT_CTX;
setenv("AFL_LLVM_CTX", "1", 1); setenv("AFL_LLVM_CTX", "1", 1);
} }
if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) { if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) {
ptr += strlen("ngram"); ptr2 += strlen("ngram");
while (*ptr && (*ptr < '0' || *ptr > '9')) while (*ptr2 && (*ptr2 < '0' || *ptr2 > '9'))
ptr++; ptr2++;
if (!*ptr) { if (!*ptr2) {
if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) if ((ptr2 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL)
FATAL( FATAL(
"you must set the NGRAM size with (e.g. for value 2) " "you must set the NGRAM size with (e.g. for value 2) "
"AFL_LLVM_INSTRUMENT=ngram-2"); "AFL_LLVM_INSTRUMENT=ngram-2");
} }
ngram_size = atoi(ptr); ngram_size = atoi(ptr2);
if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX)
FATAL( FATAL(
"NGRAM instrumentation option must be between 2 and " "NGRAM instrumentation option must be between 2 and "
@ -1332,12 +1370,12 @@ int main(int argc, char **argv, char **envp) {
"(%u)", "(%u)",
NGRAM_SIZE_MAX); NGRAM_SIZE_MAX);
instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM);
ptr = alloc_printf("%u", ngram_size); ptr2 = alloc_printf("%u", ngram_size);
setenv("AFL_LLVM_NGRAM_SIZE", ptr, 1); setenv("AFL_LLVM_NGRAM_SIZE", ptr2, 1);
} }
ptr = strtok(NULL, ":,;"); ptr2 = strtok(NULL, ":,;");
} }
@ -1448,20 +1486,28 @@ int main(int argc, char **argv, char **envp) {
" The best is LTO but it often needs RANLIB and AR settings outside " " The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n"); "of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"
#else
#define NATIVE_MSG ""
#endif
SAYF( SAYF(
"Sub-Modes: (set via env AFL_LLVM_INSTRUMENT, afl-cc selects the best " "Sub-Modes: (set via env AFL_LLVM_INSTRUMENT, afl-cc selects the best "
"available)\n" "available)\n"
" PCGUARD: Dominator tree instrumentation (best!) (README.llvm.md)\n" " PCGUARD: Dominator tree instrumentation (best!) (README.llvm.md)\n"
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
" NATIVE: use llvm's native PCGUARD instrumentation (less " NATIVE_MSG
"performant)\n"
#endif
" CLASSIC: decision target instrumentation (README.llvm.md)\n" " CLASSIC: decision target instrumentation (README.llvm.md)\n"
" CTX: CLASSIC + callee context (instrumentation/README.ctx.md)\n" " CTX: CLASSIC + callee context (instrumentation/README.ctx.md)\n"
" NGRAM-x: CLASSIC + previous path " " NGRAM-x: CLASSIC + previous path "
"((instrumentation/README.ngram.md)\n" "((instrumentation/README.ngram.md)\n"
" INSTRIM: Dominator tree (for LLVM <= 6.0) " " INSTRIM: Dominator tree (for LLVM <= 6.0) "
"(instrumentation/README.instrim.md)\n\n"); "(instrumentation/README.instrim.md)\n\n");
#undef NATIVE_MSG
SAYF( SAYF(
"Features: (see documentation links)\n" "Features: (see documentation links)\n"
@ -1595,12 +1641,17 @@ int main(int argc, char **argv, char **envp) {
if (have_lto) if (have_lto)
SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO); SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO);
if (have_llvm) if (have_llvm)
SAYF("afl-cc LLVM version %d with the the binary path \"%s\".\n", SAYF("afl-cc LLVM version %d using binary path \"%s\".\n", LLVM_MAJOR,
LLVM_MAJOR, LLVM_BINDIR); LLVM_BINDIR);
#endif #endif
#ifdef USEMMAP #if defined(USEMMAP)
#if !defined(__HAIKU__)
cc_params[cc_par_cnt++] = "-lrt";
SAYF("Compiled with shm_open support (adds -lrt when linking).\n"); SAYF("Compiled with shm_open support (adds -lrt when linking).\n");
#else
SAYF("Compiled with shm_open support.\n");
#endif
#else #else
SAYF("Compiled with shmat support.\n"); SAYF("Compiled with shmat support.\n");
#endif #endif
@ -1625,7 +1676,7 @@ int main(int argc, char **argv, char **envp) {
if (!instrument_mode) { if (!instrument_mode) {
instrument_mode = INSTRUMENT_CFG; instrument_mode = INSTRUMENT_CFG;
ptr = instrument_mode_string[instrument_mode]; // ptr = instrument_mode_string[instrument_mode];
} }

View File

@ -424,6 +424,40 @@ u8 *find_binary(u8 *fname) {
} }
/* Parses the kill signal environment variable, FATALs on error.
If the env is not set, sets the env to default_signal for the signal handlers
and returns the default_signal. */
int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
if (afl_kill_signal_env && afl_kill_signal_env[0]) {
char *endptr;
u8 signal_code;
signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
/* Did we manage to parse the full string? */
if (*endptr != '\0' || endptr == (char *)afl_kill_signal_env) {
FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
afl_kill_signal_env);
}
return signal_code;
} else {
char *sigstr = alloc_printf("%d", default_signal);
if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
/* Set the env for signal handler */
setenv("AFL_KILL_SIGNAL", sigstr, 1);
free(sigstr);
return default_signal;
}
}
void check_environment_vars(char **envp) { void check_environment_vars(char **envp) {
if (be_quiet) { return; } if (be_quiet) { return; }
@ -696,16 +730,16 @@ u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) { u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
u64 delta;
s32 t_d, t_h, t_m, t_s;
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
if (!event_ms) { if (!event_ms) {
snprintf(buf, len, "none seen yet"); snprintf(buf, len, "none seen yet");
} else { } else {
u64 delta;
s32 t_d, t_h, t_m, t_s;
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
delta = cur_ms - event_ms; delta = cur_ms - event_ms;
t_d = delta / 1000 / 60 / 60 / 24; t_d = delta / 1000 / 60 / 60 / 24;
@ -858,16 +892,16 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val) {
u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
u64 delta;
s32 t_d, t_h, t_m, t_s;
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
if (!event_ms) { if (!event_ms) {
sprintf(buf, "none seen yet"); sprintf(buf, "none seen yet");
} else { } else {
u64 delta;
s32 t_d, t_h, t_m, t_s;
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
delta = cur_ms - event_ms; delta = cur_ms - event_ms;
t_d = delta / 1000 / 60 / 60 / 24; t_d = delta / 1000 / 60 / 60 / 24;
@ -895,8 +929,8 @@ u32 get_map_size(void) {
map_size = atoi(ptr); map_size = atoi(ptr);
if (map_size < 8 || map_size > (1 << 29)) { if (map_size < 8 || map_size > (1 << 29)) {
FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8, FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8U,
1 << 29); 1U << 29);
} }

View File

@ -84,6 +84,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT; fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT; fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL; fsrv->out_file = NULL;
fsrv->kill_signal = SIGKILL;
/* exec related stuff */ /* exec related stuff */
fsrv->child_pid = -1; fsrv->child_pid = -1;
@ -95,7 +96,6 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->uses_asan = false; fsrv->uses_asan = false;
fsrv->init_child_func = fsrv_exec_child; fsrv->init_child_func = fsrv_exec_child;
list_append(&fsrv_list, fsrv); list_append(&fsrv_list, fsrv);
} }
@ -116,6 +116,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->no_unlink = from->no_unlink; fsrv_to->no_unlink = from->no_unlink;
fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode; fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
fsrv_to->crash_exitcode = from->crash_exitcode; fsrv_to->crash_exitcode = from->crash_exitcode;
fsrv_to->kill_signal = from->kill_signal;
// These are forkserver specific. // These are forkserver specific.
fsrv_to->out_dir_fd = -1; fsrv_to->out_dir_fd = -1;
@ -213,7 +214,7 @@ restart_select:
static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
unsigned char tmp[4] = {0, 0, 0, 0}; unsigned char tmp[4] = {0, 0, 0, 0};
pid_t child_pid = -1; pid_t child_pid;
if (!be_quiet) { ACTF("Using Fauxserver:"); } if (!be_quiet) { ACTF("Using Fauxserver:"); }
@ -559,12 +560,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!time_ms) { if (!time_ms) {
kill(fsrv->fsrv_pid, SIGKILL); kill(fsrv->fsrv_pid, fsrv->kill_signal);
} else if (time_ms > fsrv->init_tmout) { } else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1; fsrv->last_run_timed_out = 1;
kill(fsrv->fsrv_pid, SIGKILL); kill(fsrv->fsrv_pid, fsrv->kill_signal);
} else { } else {
@ -944,10 +945,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
static void afl_fsrv_kill(afl_forkserver_t *fsrv) { static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
if (fsrv->child_pid > 0) { kill(fsrv->child_pid, SIGKILL); } if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
if (fsrv->fsrv_pid > 0) { if (fsrv->fsrv_pid > 0) {
kill(fsrv->fsrv_pid, SIGKILL); kill(fsrv->fsrv_pid, fsrv->kill_signal);
if (waitpid(fsrv->fsrv_pid, NULL, 0) <= 0) { WARNF("error waitpid\n"); } if (waitpid(fsrv->fsrv_pid, NULL, 0) <= 0) { WARNF("error waitpid\n"); }
} }
@ -1091,7 +1092,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* If there was no response from forkserver after timeout seconds, /* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */ we kill the child. The forkserver should inform us afterwards */
kill(fsrv->child_pid, SIGKILL); kill(fsrv->child_pid, fsrv->kill_signal);
fsrv->last_run_timed_out = 1; fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }
@ -1104,7 +1105,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
"Unable to communicate with fork server. Some possible reasons:\n\n" "Unable to communicate with fork server. Some possible reasons:\n\n"
" - You've run out of memory. Use -m to increase the the memory " " - You've run out of memory. Use -m to increase the the memory "
"limit\n" "limit\n"
" to something higher than %lld.\n" " to something higher than %llu.\n"
" - The binary or one of the libraries it uses manages to " " - The binary or one of the libraries it uses manages to "
"create\n" "create\n"
" threads before the forkserver initializes.\n" " threads before the forkserver initializes.\n"
@ -1137,16 +1138,18 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* Report outcome to caller. */ /* Report outcome to caller. */
if (WIFSIGNALED(fsrv->child_status) && !*stop_soon_p) { /* Did we timeout? */
if (unlikely(fsrv->last_run_timed_out)) {
fsrv->last_kill_signal = fsrv->kill_signal;
return FSRV_RUN_TMOUT;
}
/* Did we crash? */
if (unlikely(WIFSIGNALED(fsrv->child_status) && !*stop_soon_p)) {
fsrv->last_kill_signal = WTERMSIG(fsrv->child_status); fsrv->last_kill_signal = WTERMSIG(fsrv->child_status);
if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) {
return FSRV_RUN_TMOUT;
}
return FSRV_RUN_CRASH; return FSRV_RUN_CRASH;
} }

View File

@ -703,7 +703,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (!classified) { if (!classified) {
classify_counts(&afl->fsrv); classify_counts(&afl->fsrv);
classified = 1; // classified = 1;
} }

View File

@ -266,7 +266,7 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
if (afl->extras_cnt > afl->max_det_extras) { if (afl->extras_cnt > afl->max_det_extras) {
WARNF("More than %d tokens - will use them probabilistically.", WARNF("More than %u tokens - will use them probabilistically.",
afl->max_det_extras); afl->max_det_extras);
} }
@ -431,7 +431,6 @@ void dedup_extras(afl_state_t *afl) {
/* Adds a new extra / dict entry. */ /* Adds a new extra / dict entry. */
void add_extra(afl_state_t *afl, u8 *mem, u32 len) { void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
u32 i, found = 0; u32 i, found = 0;
for (i = 0; i < afl->extras_cnt; i++) { for (i = 0; i < afl->extras_cnt; i++) {
@ -451,6 +450,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
if (len > MAX_DICT_FILE) { if (len > MAX_DICT_FILE) {
u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
WARNF("Extra '%.*s' is too big (%s, limit is %s), skipping file!", (int)len, WARNF("Extra '%.*s' is too big (%s, limit is %s), skipping file!", (int)len,
mem, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len), mem, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
@ -481,7 +481,7 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
if (afl->extras_cnt == afl->max_det_extras + 1) { if (afl->extras_cnt == afl->max_det_extras + 1) {
WARNF("More than %d tokens - will use them probabilistically.", WARNF("More than %u tokens - will use them probabilistically.",
afl->max_det_extras); afl->max_det_extras);
} }

View File

@ -316,16 +316,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
/* Initialize trimming in the custom mutator */ /* Initialize trimming in the custom mutator */
afl->stage_cur = 0; afl->stage_cur = 0;
afl->stage_max = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len); s32 retval = mutator->afl_custom_init_trim(mutator->data, in_buf, q->len);
if (unlikely(afl->stage_max) < 0) { if (unlikely(retval) < 0) {
FATAL("custom_init_trim error ret: %d", afl->stage_max); FATAL("custom_init_trim error ret: %d", retval);
} else {
afl->stage_max = retval;
} }
if (afl->not_on_tty && afl->debug) { if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, SAYF("[Custom Trimming] START: Max %u iterations, %u bytes", afl->stage_max,
q->len); q->len);
} }
@ -343,7 +347,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (unlikely(!retbuf)) { if (unlikely(!retbuf)) {
FATAL("custom_trim failed (ret %zd)", retlen); FATAL("custom_trim failed (ret %zu)", retlen);
} else if (unlikely(retlen > orig_len)) { } else if (unlikely(retlen > orig_len)) {
@ -409,7 +413,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (afl->not_on_tty && afl->debug) { if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", SAYF("[Custom Trimming] SUCCESS: %u/%u iterations (now at %u bytes)",
afl->stage_cur, afl->stage_max, q->len); afl->stage_cur, afl->stage_max, q->len);
} }
@ -417,16 +421,20 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
} else { } else {
/* Tell the custom mutator that the trimming was unsuccessful */ /* Tell the custom mutator that the trimming was unsuccessful */
afl->stage_cur = mutator->afl_custom_post_trim(mutator->data, 0); s32 retval2 = mutator->afl_custom_post_trim(mutator->data, 0);
if (unlikely(afl->stage_cur < 0)) { if (unlikely(retval2 < 0)) {
FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); FATAL("Error ret in custom_post_trim: %d", retval2);
} else {
afl->stage_cur = retval2;
} }
if (afl->not_on_tty && afl->debug) { if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, SAYF("[Custom Trimming] FAILURE: %u/%u iterations", afl->stage_cur,
afl->stage_max); afl->stage_max);
} }

View File

@ -368,7 +368,7 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
u8 fuzz_one_original(afl_state_t *afl) { u8 fuzz_one_original(afl_state_t *afl) {
s32 len, temp_len; u32 len, temp_len;
u32 j; u32 j;
u32 i; u32 i;
u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
@ -545,7 +545,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
else else
orig_perf = perf_score = calculate_score(afl, afl->queue_cur); orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
if (unlikely(perf_score <= 0)) { goto abandon_entry; } if (unlikely(perf_score == 0)) { goto abandon_entry; }
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) { if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
@ -902,7 +902,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
orig_hit_cnt = new_hit_cnt; orig_hit_cnt = new_hit_cnt;
for (i = 0; (s32)i < len - 1; ++i) { for (i = 0; i < len - 1; ++i) {
/* Let's consult the effector map... */ /* Let's consult the effector map... */
@ -945,7 +945,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
orig_hit_cnt = new_hit_cnt; orig_hit_cnt = new_hit_cnt;
for (i = 0; (s32)i < len - 3; ++i) { for (i = 0; i < len - 3; ++i) {
/* Let's consult the effector map... */ /* Let's consult the effector map... */
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] && if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
@ -1405,7 +1405,7 @@ skip_arith:
orig_hit_cnt = new_hit_cnt; orig_hit_cnt = new_hit_cnt;
for (i = 0; (s32)i < len - 1; ++i) { for (i = 0; i < len - 1; ++i) {
u16 orig = *(u16 *)(out_buf + i); u16 orig = *(u16 *)(out_buf + i);
@ -1493,7 +1493,7 @@ skip_arith:
orig_hit_cnt = new_hit_cnt; orig_hit_cnt = new_hit_cnt;
for (i = 0; (s32)i < len - 3; i++) { for (i = 0; i < len - 3; i++) {
u32 orig = *(u32 *)(out_buf + i); u32 orig = *(u32 *)(out_buf + i);
@ -1850,7 +1850,7 @@ custom_mutator_stage:
if (unlikely(!mutated_buf)) { if (unlikely(!mutated_buf)) {
FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size); FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size);
} }
@ -2026,7 +2026,7 @@ havoc_stage:
el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE); el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
if (unlikely(!custom_havoc_buf)) { if (unlikely(!custom_havoc_buf)) {
FATAL("Error in custom_havoc (return %zd)", new_len); FATAL("Error in custom_havoc (return %zu)", new_len);
} }
@ -2458,7 +2458,7 @@ havoc_stage:
u32 use_extra = rand_below(afl, afl->a_extras_cnt); u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len; u32 extra_len = afl->a_extras[use_extra].len;
if ((s32)extra_len > temp_len) { break; } if (extra_len > temp_len) { break; }
u32 insert_at = rand_below(afl, temp_len - extra_len + 1); u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION #ifdef INTROSPECTION
@ -2476,7 +2476,7 @@ havoc_stage:
u32 use_extra = rand_below(afl, afl->extras_cnt); u32 use_extra = rand_below(afl, afl->extras_cnt);
u32 extra_len = afl->extras[use_extra].len; u32 extra_len = afl->extras[use_extra].len;
if ((s32)extra_len > temp_len) { break; } if (extra_len > temp_len) { break; }
u32 insert_at = rand_below(afl, temp_len - extra_len + 1); u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION #ifdef INTROSPECTION
@ -2577,7 +2577,7 @@ havoc_stage:
u32 copy_from, copy_to, copy_len; u32 copy_from, copy_to, copy_len;
copy_len = choose_block_len(afl, new_len - 1); copy_len = choose_block_len(afl, new_len - 1);
if ((s32)copy_len > temp_len) copy_len = temp_len; if (copy_len > temp_len) copy_len = temp_len;
copy_from = rand_below(afl, new_len - copy_len + 1); copy_from = rand_below(afl, new_len - copy_len + 1);
copy_to = rand_below(afl, temp_len - copy_len + 1); copy_to = rand_below(afl, temp_len - copy_len + 1);
@ -2952,7 +2952,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
else else
orig_perf = perf_score = calculate_score(afl, afl->queue_cur); orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
if (unlikely(perf_score <= 0)) { goto abandon_entry; } if (unlikely(perf_score == 0)) { goto abandon_entry; }
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) { if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {

View File

@ -494,11 +494,12 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
void destroy_queue(afl_state_t *afl) { void destroy_queue(afl_state_t *afl) {
struct queue_entry *q; u32 i;
u32 i;
for (i = 0; i < afl->queued_paths; i++) { for (i = 0; i < afl->queued_paths; i++) {
struct queue_entry *q;
q = afl->queue_buf[i]; q = afl->queue_buf[i];
ck_free(q->fname); ck_free(q->fname);
ck_free(q->trace_mini); ck_free(q->trace_mini);
@ -1001,7 +1002,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
if (unlikely(!q->testcase_buf)) { if (unlikely(!q->testcase_buf)) {
PFATAL("Unable to malloc '%s' with len %d", q->fname, len); PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
} }

View File

@ -99,12 +99,12 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
} }
static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) { static void xor_replace(u8 *buf, u32 len) {
u32 i; u32 i;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
buf[i] = rand_below(afl, 256); buf[i] ^= 0xff;
} }
@ -115,8 +115,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
struct range *ranges = add_range(NULL, 0, len); struct range *ranges = add_range(NULL, 0, len);
u8 * backup = ck_alloc_nozero(len); u8 * backup = ck_alloc_nozero(len);
u8 needs_write = 0;
u64 orig_hit_cnt, new_hit_cnt; u64 orig_hit_cnt, new_hit_cnt;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes; orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@ -136,7 +134,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
/* Range not empty */ /* Range not empty */
memcpy(backup, buf + rng->start, s); memcpy(backup, buf + rng->start, s);
rand_replace(afl, buf + rng->start, s); xor_replace(buf + rng->start, s);
u64 cksum; u64 cksum;
u64 start_us = get_cur_time_us(); u64 start_us = get_cur_time_us();
@ -158,10 +156,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
ranges = add_range(ranges, rng->start + s / 2 + 1, rng->end); ranges = add_range(ranges, rng->start + s / 2 + 1, rng->end);
memcpy(buf + rng->start, backup, s); memcpy(buf + rng->start, backup, s);
} else {
needs_write = 1;
} }
} }
@ -191,32 +185,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
} }
// save the input with the high entropy
if (needs_write) {
s32 fd;
if (afl->no_unlink) {
fd = open(afl->queue_cur->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
} else {
unlink(afl->queue_cur->fname); /* ignore errors */
fd = open(afl->queue_cur->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
}
if (fd < 0) { PFATAL("Unable to create '%s'", afl->queue_cur->fname); }
ck_write(fd, buf, len, afl->queue_cur->fname);
afl->queue_cur->len = len; // no-op, just to be 100% safe
close(fd);
}
return 0; return 0;
checksum_fail: checksum_fail:
@ -232,8 +200,6 @@ checksum_fail:
} }
// TODO: clang notices a _potential_ leak of mem pointed to by rng
return 1; return 1;
} }
@ -479,6 +445,10 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u32 k; u32 k;
u8 cons_ff = 0, cons_0 = 0; u8 cons_ff = 0, cons_0 = 0;
if (shape > sizeof(v))
FATAL("shape is greater than %zu, please report!", sizeof(v));
for (k = 0; k < shape; ++k) { for (k = 0; k < shape; ++k) {
if (b[k] == 0) { if (b[k] == 0) {
@ -487,7 +457,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
} else if (b[k] == 0xff) { } else if (b[k] == 0xff) {
++cons_0; ++cons_ff;
} else { } else {
@ -701,12 +671,12 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
u8 status = 0; u8 status = 0;
// opt not in the paper // opt not in the paper
u32 fails = 0; // u32 fails = 0;
u8 found_one = 0; u8 found_one = 0;
for (i = 0; i < loggeds; ++i) { for (i = 0; i < loggeds; ++i) {
fails = 0; u32 fails = 0;
struct cmpfn_operands *o = struct cmpfn_operands *o =
&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i]; &((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i];
@ -802,13 +772,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
u64 exec_cksum) { u64 exec_cksum) {
u8 r = 1; u8 r = 1;
if (afl->orig_cmp_map == NULL) { if (unlikely(!afl->orig_cmp_map)) {
afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map)); afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
} }
if (afl->pass_stats == NULL) { if (unlikely(!afl->pass_stats)) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W); afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
@ -888,7 +858,7 @@ exit_its:
afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt; afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs; afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs;
memcpy(orig_buf, buf, len); memcpy(buf, orig_buf, len);
return r; return r;

View File

@ -430,6 +430,13 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
/* OK, let's collect some stats about the performance of this test case. /* OK, let's collect some stats about the performance of this test case.
This is used for fuzzing air time calculations in calculate_score(). */ This is used for fuzzing air time calculations in calculate_score(). */
if (unlikely(!afl->stage_max)) {
// Pretty sure this cannot happen, yet scan-build complains.
FATAL("BUG: stage_max should not be 0 here! Please report this condition.");
}
q->exec_us = (stop_us - start_us) / afl->stage_max; q->exec_us = (stop_us - start_us) / afl->stage_max;
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits); q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
q->handicap = handicap; q->handicap = handicap;
@ -682,7 +689,7 @@ void sync_fuzzers(afl_state_t *afl) {
// same time. If so, the first temporary main node running again will demote // same time. If so, the first temporary main node running again will demote
// themselves so this is not an issue // themselves so this is not an issue
u8 path[PATH_MAX]; // u8 path2[PATH_MAX];
afl->is_main_node = 1; afl->is_main_node = 1;
sprintf(path, "%s/is_main_node", afl->out_dir); sprintf(path, "%s/is_main_node", afl->out_dir);
int fd = open(path, O_CREAT | O_RDWR, 0644); int fd = open(path, O_CREAT | O_RDWR, 0644);

View File

@ -418,6 +418,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
(u8 *)get_afl_env(afl_environment_variables[i]); (u8 *)get_afl_env(afl_environment_variables[i]);
#endif #endif
} else if (!strncmp(env, "AFL_KILL_SIGNAL",
afl_environment_variable_len)) {
afl->afl_env.afl_kill_signal =
(u8 *)get_afl_env(afl_environment_variables[i]);
} }
} else { } else {
@ -524,8 +531,8 @@ void afl_states_stop(void) {
LIST_FOREACH(&afl_states, afl_state_t, { LIST_FOREACH(&afl_states, afl_state_t, {
if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, SIGKILL); if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, el->fsrv.kill_signal);
if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, SIGKILL); if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, el->fsrv.kill_signal);
}); });

View File

@ -31,8 +31,7 @@
void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
char *val; u8 fn[PATH_MAX];
u8 fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
FILE *f = create_ffile(fn); FILE *f = create_ffile(fn);
u32 i; u32 i;
@ -44,6 +43,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
for (i = 0; i < s_afl_env; ++i) { for (i = 0; i < s_afl_env; ++i) {
char *val;
if ((val = getenv(afl_environment_variables[i])) != NULL) { if ((val = getenv(afl_environment_variables[i])) != NULL) {
fprintf(f, "%s=%s\n", afl_environment_variables[i], val); fprintf(f, "%s=%s\n", afl_environment_variables[i], val);
@ -228,7 +228,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
if (afl->virgin_bits[i] != 0xff) { if (afl->virgin_bits[i] != 0xff) {
fprintf(f, " %d[%02x]", i, afl->virgin_bits[i]); fprintf(f, " %u[%02x]", i, afl->virgin_bits[i]);
} }
@ -238,7 +238,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
fprintf(f, "var_bytes :"); fprintf(f, "var_bytes :");
for (i = 0; i < afl->fsrv.map_size; i++) { for (i = 0; i < afl->fsrv.map_size; i++) {
if (afl->var_bytes[i]) { fprintf(f, " %d", i); } if (afl->var_bytes[i]) { fprintf(f, " %u", i); }
} }
@ -1163,7 +1163,7 @@ void show_init_stats(afl_state_t *afl) {
} else { } else {
ACTF("-t option specified. We'll use an exec timeout of %d ms.", ACTF("-t option specified. We'll use an exec timeout of %u ms.",
afl->fsrv.exec_tmout); afl->fsrv.exec_tmout);
} }

View File

@ -76,8 +76,17 @@ static void at_exit() {
} }
if (pid1 > 0) { kill(pid1, SIGKILL); } int kill_signal = SIGKILL;
if (pid2 > 0) { kill(pid2, SIGKILL); }
/* AFL_KILL_SIGNAL should already be a valid int at this point */
if (getenv("AFL_KILL_SIGNAL")) {
kill_signal = atoi(getenv("AFL_KILL_SIGNAL"));
}
if (pid1 > 0) { kill(pid1, kill_signal); }
if (pid2 > 0) { kill(pid2, kill_signal); }
} }
@ -99,8 +108,8 @@ static void usage(u8 *argv0, int more_help) {
" lin, quad> -- see docs/power_schedules.md\n" " lin, quad> -- see docs/power_schedules.md\n"
" -f file - location read by the fuzzed program (default: stdin " " -f file - location read by the fuzzed program (default: stdin "
"or @@)\n" "or @@)\n"
" -t msec - timeout for each run (auto-scaled, 50-%d ms)\n" " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n"
" -m megs - memory limit for child process (%d MB, 0 = no limit)\n" " -m megs - memory limit for child process (%u MB, 0 = no limit)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n" " -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine " " -W - use qemu-based instrumentation with Wine (Wine "
@ -185,10 +194,11 @@ static void usage(u8 *argv0, int more_help) {
"AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n" "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n"
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n" "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n" "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n" "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n" " the target was compiled for\n"
"AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n" "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
@ -299,7 +309,8 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/; s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/;
u64 prev_queued = 0; u64 prev_queued = 0;
u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = MAP_SIZE; u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0,
map_size = get_map_size();
u8 *extras_dir[4]; u8 *extras_dir[4];
u8 mem_limit_given = 0, exit_1 = 0, debug = 0, u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
extras_dir_cnt = 0 /*, have_p = 0*/; extras_dir_cnt = 0 /*, have_p = 0*/;
@ -326,7 +337,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; } if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
map_size = get_map_size(); // map_size = get_map_size();
afl_state_init(afl, map_size); afl_state_init(afl, map_size);
afl->debug = debug; afl->debug = debug;
afl_fsrv_init(&afl->fsrv); afl_fsrv_init(&afl->fsrv);
@ -976,6 +987,9 @@ int main(int argc, char **argv_orig, char **envp) {
#endif #endif
afl->fsrv.kill_signal =
parse_afl_kill_signal_env(afl->afl_env.afl_kill_signal, SIGKILL);
setup_signal_handlers(); setup_signal_handlers();
check_asan_opts(afl); check_asan_opts(afl);
@ -1534,7 +1548,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->pending_not_fuzzed) { if (!afl->pending_not_fuzzed) {
FATAL("We need at least on valid input seed that does not crash!"); FATAL("We need at least one valid input seed that does not crash!");
} }

View File

@ -187,7 +187,7 @@ static void edit_params(int argc, char **argv) {
if (debug) if (debug)
DEBUGF( DEBUGF(
"passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s " "passthrough=%s instrim=%u, gold_pos=%u, gold_present=%s "
"inst_present=%s rt_present=%s rt_lto_present=%s\n", "inst_present=%s rt_present=%s rt_lto_present=%s\n",
passthrough ? "true" : "false", instrim, gold_pos, passthrough ? "true" : "false", instrim, gold_pos,
gold_present ? "true" : "false", inst_present ? "true" : "false", gold_present ? "true" : "false", inst_present ? "true" : "false",
@ -252,11 +252,11 @@ static void edit_params(int argc, char **argv) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
s32 pid, i, status; s32 pid, i, status;
u8 * ptr; // u8 * ptr;
char thecwd[PATH_MAX]; char thecwd[PATH_MAX];
if ((ptr = getenv("AFL_LD_CALLER")) != NULL) { if (getenv("AFL_LD_CALLER") != NULL) {
FATAL("ld loop detected! Set AFL_REAL_LD!\n"); FATAL("ld loop detected! Set AFL_REAL_LD!\n");

View File

@ -662,7 +662,7 @@ static void usage(u8 *argv0) {
"Execution control settings:\n" "Execution control settings:\n"
" -t msec - timeout for each run (none)\n" " -t msec - timeout for each run (none)\n"
" -m megs - memory limit for child process (%d MB)\n" " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use Unicorn-based instrumentation (Unicorn mode)\n" " -U - use Unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine mode)\n" " -W - use qemu-based instrumentation with Wine (Wine mode)\n"
@ -693,12 +693,13 @@ static void usage(u8 *argv0) {
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as " "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
"crash\n" "crash\n"
"AFL_DEBUG: enable extra developer output\n" "AFL_DEBUG: enable extra developer output\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during " "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
"startup (in milliseconds)\n" "startup (in milliseconds)\n"
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, "
"etc. (default: SIGKILL)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_QUIET: do not print extra informational output\n", "AFL_QUIET: do not print extra informational output\n",
argv0, MEM_LIMIT, doc_path); argv0, MEM_LIMIT, doc_path);
@ -1014,9 +1015,9 @@ int main(int argc, char **argv_orig, char **envp) {
DIR * dir_in, *dir_out = NULL; DIR * dir_in, *dir_out = NULL;
struct dirent *dir_ent; struct dirent *dir_ent;
int done = 0; // int done = 0;
u8 infile[PATH_MAX], outfile[PATH_MAX]; u8 infile[PATH_MAX], outfile[PATH_MAX];
u8 wait_for_gdb = 0; u8 wait_for_gdb = 0;
#if !defined(DT_REG) #if !defined(DT_REG)
struct stat statbuf; struct stat statbuf;
#endif #endif
@ -1090,11 +1091,11 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) { if (get_afl_env("AFL_DEBUG")) {
int i = optind; int j = optind;
DEBUGF("%s:", fsrv->target_path); DEBUGF("%s:", fsrv->target_path);
while (argv[i] != NULL) { while (argv[j] != NULL) {
SAYF(" \"%s\"", argv[i++]); SAYF(" \"%s\"", argv[j++]);
} }
@ -1115,6 +1116,9 @@ int main(int argc, char **argv_orig, char **envp) {
} }
fsrv->kill_signal =
parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
if (getenv("AFL_CRASH_EXITCODE")) { if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
@ -1143,7 +1147,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz); shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
while (done == 0 && (dir_ent = readdir(dir_in))) { while ((dir_ent = readdir(dir_in))) {
if (dir_ent->d_name[0] == '.') { if (dir_ent->d_name[0] == '.') {

View File

@ -835,8 +835,8 @@ static void usage(u8 *argv0) {
"Execution control settings:\n" "Execution control settings:\n"
" -f file - input file read by the tested program (stdin)\n" " -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%d ms)\n" " -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%d MB)\n" " -m megs - memory limit for child process (%u MB)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn mode)\n" " -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine " " -W - use qemu-based instrumentation with Wine (Wine "
@ -855,6 +855,7 @@ static void usage(u8 *argv0) {
"Environment variables used:\n" "Environment variables used:\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n" " the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
@ -1134,6 +1135,9 @@ int main(int argc, char **argv_orig, char **envp) {
} }
fsrv->kill_signal =
parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
if (getenv("AFL_CRASH_EXITCODE")) { if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);

View File

@ -106,7 +106,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
;; ;;
esac esac
} else { } else {
$ECHO "$GRAY[*] no bash available, cannot test afl-cmin.bash" $ECHO "$GREY[*] no bash available, cannot test afl-cmin.bash"
} }
fi fi
../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
@ -210,7 +210,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CNT=`ls in2/* 2>/dev/null | wc -l` CNT=`ls in2/* 2>/dev/null | wc -l`
case "$CNT" in case "$CNT" in
*2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;; *2) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
1) { \ *1|1) { # allow leading whitecase for portability
test -s in2/* && $ECHO "$YELLOW[?] afl-cmin did minimize to one testcase. This can be a bug or due compiler optimization." test -s in2/* && $ECHO "$YELLOW[?] afl-cmin did minimize to one testcase. This can be a bug or due compiler optimization."
test -s in2/* || { test -s in2/* || {
$ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases ($CNT)" $ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases ($CNT)"
@ -229,8 +229,8 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
CNT=`ls in2/* 2>/dev/null | wc -l` CNT=`ls in2/* 2>/dev/null | wc -l`
case "$CNT" in case "$CNT" in
*2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;; *2) $ECHO "$GREEN[+] afl-cmin.bash correctly minimized the number of testcases" ;;
1) { \ *1|1) { # allow leading whitecase for portability
test -s in2/* && $ECHO "$YELLOW[?] afl-cmin.bash did minimize to one testcase. This can be a bug or due compiler optimization." test -s in2/* && $ECHO "$YELLOW[?] afl-cmin.bash did minimize to one testcase. This can be a bug or due compiler optimization."
test -s in2/* || { test -s in2/* || {
$ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)" $ECHO "$RED[!] afl-cmin.bash did not correctly minimize the number of testcases ($CNT)"
CODE=1 CODE=1
@ -242,7 +242,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
;; ;;
esac esac
} else { } else {
$ECHO "$GRAY[*] no bash available, cannot test afl-cmin.bash" $ECHO "$GREY[*] no bash available, cannot test afl-cmin.bash"
} }
fi fi
../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1 ../afl-tmin -m ${MEM_LIMIT} -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1

View File

@ -44,7 +44,7 @@ echo "[*] Performing basic sanity checks..."
PLT=`uname -s` PLT=`uname -s`
if [ ! "$PLT" = "Linux" ] && [ ! "$PLT" = "Darwin" ] && [ ! "$PLT" = "FreeBSD" ] && [ ! "$PLT" = "NetBSD" ] && [ ! "$PLT" = "OpenBSD" ]; then if [ ! "$PLT" = "Linux" ] && [ ! "$PLT" = "Darwin" ] && [ ! "$PLT" = "FreeBSD" ] && [ ! "$PLT" = "NetBSD" ] && [ ! "$PLT" = "OpenBSD" ] && [ ! "$PLT" = "DragonFly" ]; then
echo "[-] Error: Unicorn instrumentation is unsupported on $PLT." echo "[-] Error: Unicorn instrumentation is unsupported on $PLT."
exit 1 exit 1
@ -89,6 +89,12 @@ if [ "$PLT" = "FreeBSD" ]; then
TARCMD=gtar TARCMD=gtar
fi fi
if [ "$PLT" = "DragonFly" ]; then
MAKECMD=gmake
CORES=`sysctl -n hw.ncpu`
TARCMD=tar
fi
if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then if [ "$PLT" = "NetBSD" ] || [ "$PLT" = "OpenBSD" ]; then
MAKECMD=gmake MAKECMD=gmake
CORES=`sysctl -n hw.ncpu` CORES=`sysctl -n hw.ncpu`
@ -150,6 +156,7 @@ if [ $? -eq 0 ]; then
echo "[*] initializing unicornafl submodule" echo "[*] initializing unicornafl submodule"
git submodule init || exit 1 git submodule init || exit 1
git submodule update ./unicornafl 2>/dev/null # ignore errors git submodule update ./unicornafl 2>/dev/null # ignore errors
git submodule sync ./unicornafl 2>/dev/null # ignore errors
else else
echo "[*] cloning unicornafl" echo "[*] cloning unicornafl"
test -d unicornafl || { test -d unicornafl || {

View File

@ -1,12 +1,8 @@
//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// //===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/* This file allows to fuzz libFuzzer-style target functions /* This file allows to fuzz libFuzzer-style target functions
(LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing.
Usage: Usage:
################################################################################ ################################################################################
@ -25,25 +21,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
EOF EOF
# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c clang -c aflpp_driver.c
# Build afl-compiler-rt.o.c from the AFL distribution. # Build afl-compiler-rt.o.c from the AFL distribution.
clang -c -w $AFL_HOME/instrumentation/afl-compiler-rt.o.c clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c
# Build this file, link it with afl-compiler-rt.o.o and the target code. # Build this file, link it with afl-compiler-rt.o.o and the target code.
clang++ afl_driver.cpp test_fuzzer.o afl-compiler-rt.o.o afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o
# Run AFL: # Run AFL:
rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
################################################################################ ################################################################################
AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
specified. If the file does not exist, it is created. This is useful for getting
stack traces (when using ASAN for example) or original error messages on hard
to reproduce bugs. Note that any content written to stderr will be written to
this file instead of stderr's usual location.
AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
If 1, close stdout at startup. If 2 close stderr; if 3 close both.
*/ */
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
@ -65,47 +53,6 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
#include "hash.h" #include "hash.h"
#endif #endif
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0x100000
#endif
#define MAX_DUMMY_SIZE 256000
// Platform detection. Copied from FuzzerInternal.h
#ifdef __linux__
#define LIBFUZZER_LINUX 1
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __APPLE__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 1
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __NetBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 1
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __FreeBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 1
#define LIBFUZZER_OPENBSD 0
#elif __OpenBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 1
#else
#error "Support for your platform has not been implemented"
#endif
int __afl_sharedmem_fuzzing = 1; int __afl_sharedmem_fuzzing = 1;
extern unsigned int * __afl_fuzz_len; extern unsigned int * __afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr; extern unsigned char *__afl_fuzz_ptr;

View File

@ -1,4 +1,4 @@
#define __GNU_SOURCE #define _GNU_SOURCE
#include <dlfcn.h> #include <dlfcn.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>

View File

@ -1,10 +1,10 @@
all: all:
afl-clang-fast -o persistent_demo persistent_demo.c ../../afl-clang-fast -o persistent_demo persistent_demo.c
afl-clang-fast -o persistent_demo_new persistent_demo_new.c ../../afl-clang-fast -o persistent_demo_new persistent_demo_new.c
AFL_DONT_OPTIMIZE=1 afl-clang-fast -o test-instr test-instr.c AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -o test-instr test-instr.c
document: document:
AFL_DONT_OPTIMIZE=1 afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c AFL_DONT_OPTIMIZE=1 ../../afl-clang-fast -D_AFL_DOCUMENT_MUTATIONS -o test-instr test-instr.c
clean: clean:
rm -f persistent_demo persistent_demo_new test-instr rm -f persistent_demo persistent_demo_new test-instr

View File

@ -2,7 +2,7 @@
int target_func(unsigned char *buf, int size) { int target_func(unsigned char *buf, int size) {
printf("buffer:%p, size:%p\n", buf, size); printf("buffer:%p, size:%d\n", buf, size);
switch (buf[0]) { switch (buf[0]) {
case 1: case 1: