diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..478c7a8416 --- /dev/null +++ b/.clang-format @@ -0,0 +1,148 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never +... + diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 04df38c52e..c2633f4451 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -2,8 +2,6 @@ //! They may be inserted as part of mutations during fuzzing. #[cfg(feature = "std")] use crate::mutators::str_decode; -#[cfg(target_os = "linux")] -use alloc::string::ToString; use alloc::vec::Vec; #[cfg(target_os = "linux")] use core::slice::from_raw_parts; @@ -110,9 +108,9 @@ impl Tokens { pub unsafe fn from_ptrs(token_start: *const u8, token_stop: *const u8) -> Result { let mut ret = Self::default(); if token_start.is_null() || token_stop.is_null() { - return Err(Error::IllegalArgument("token_start or token_stop is null. If you are using autotokens() you likely did not build your target with the \"AutoTokens\"-pass".to_string())); + return Ok(Self::new()); } - if token_stop <= token_start { + if token_stop < token_start { return Err(Error::IllegalArgument(format!( "Tried to create tokens from illegal section: stop < start ({:?} < {:?})", token_stop, token_start diff --git a/libafl_cc/src/afl-coverage-pass.cc b/libafl_cc/src/afl-coverage-pass.cc index 281072c295..bf9cb85f4d 100644 --- a/libafl_cc/src/afl-coverage-pass.cc +++ b/libafl_cc/src/afl-coverage-pass.cc @@ -72,15 +72,35 @@ typedef uint32_t prev_loc_t; using namespace llvm; -static cl::opt Debug("debug", cl::desc("Debug prints"), cl::init(false), cl::NotHidden); -static cl::opt InstRatio("inst_ratio", cl::desc("Instrumentation ratio in percentage"), cl::init(100), cl::NotHidden); -static cl::opt NotZero("not_zero", cl::desc("Never hit 0 again in the hitcount"), cl::init(true), cl::NotHidden); -static cl::opt Ngram("ngram", cl::desc("Size of the Ngram instrumentation (0 to disable)"), cl::init(0), cl::NotHidden); -static cl::opt CtxK("ctx_k", cl::desc("Size of the context for K-Ctx context sensitivity (0 to disable)"), cl::init(0), cl::NotHidden); -static cl::opt Ctx("ctx", cl::desc("Enable full context sensitive coverage"), cl::init(false), cl::NotHidden); -static cl::opt ThreadSafe("thread_safe", cl::desc("Use the thread safe instrumentation"), cl::init(false), cl::NotHidden); -static cl::opt DumpCFG("dump_afl_cfg", cl::desc("Dump CFG containing AFL-style edge index"), cl::init(false), cl::NotHidden); -static cl::opt DumpCFGPath("dump_afl_cfg_path", cl::desc("Path to dump CFG containing AFL-style edge index"), cl::init(".cfg"), cl::NotHidden); +static cl::opt Debug("debug", cl::desc("Debug prints"), cl::init(false), + cl::NotHidden); +static cl::opt InstRatio( + "inst_ratio", cl::desc("Instrumentation ratio in percentage"), + cl::init(100), cl::NotHidden); +static cl::opt NotZero("not_zero", + cl::desc("Never hit 0 again in the hitcount"), + cl::init(true), cl::NotHidden); +static cl::opt Ngram( + "ngram", cl::desc("Size of the Ngram instrumentation (0 to disable)"), + cl::init(0), cl::NotHidden); +static cl::opt CtxK( + "ctx_k", + cl::desc( + "Size of the context for K-Ctx context sensitivity (0 to disable)"), + cl::init(0), cl::NotHidden); +static cl::opt Ctx("ctx", + cl::desc("Enable full context sensitive coverage"), + cl::init(false), cl::NotHidden); +static cl::opt ThreadSafe("thread_safe", + cl::desc("Use the thread safe instrumentation"), + cl::init(false), cl::NotHidden); +static cl::opt DumpCFG( + "dump_afl_cfg", cl::desc("Dump CFG containing AFL-style edge index"), + cl::init(false), cl::NotHidden); +static cl::opt DumpCFGPath( + "dump_afl_cfg_path", + cl::desc("Path to dump CFG containing AFL-style edge index"), + cl::init(".cfg"), cl::NotHidden); namespace { @@ -96,7 +116,6 @@ class AFLCoverage : public ModulePass { #endif // initInstrumentList(); - } #ifdef USE_NEW_PM @@ -106,11 +125,10 @@ class AFLCoverage : public ModulePass { #endif protected: - uint32_t map_size = MAP_SIZE; - uint32_t function_minimum_size = 1; - DenseMap bb_to_cur_loc; - DenseMap entry_bb; - + uint32_t map_size = MAP_SIZE; + uint32_t function_minimum_size = 1; + DenseMap bb_to_cur_loc; + DenseMap entry_bb; }; } // namespace @@ -118,33 +136,30 @@ class AFLCoverage : public ModulePass { #ifdef USE_NEW_PM extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { - return { - LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { -#if 1 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - MPM.addPass(AFLCoverage()); - } - ); -/* TODO LTO registration */ -#else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback( - [](StringRef Name, ModulePassManager &MPM, ArrayRef) { - if ( Name == "AFLCoverage" ) { - MPM.addPass(AFLCoverage()); - return true; - } else { - return false; - } - } - ); -#endif - } - }; + return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + #if 1 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + MPM.addPass(AFLCoverage()); + }); + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + if (Name == "AFLCoverage") { + MPM.addPass(AFLCoverage()); + return true; + } else { + return false; + } + }); + #endif + }}; } #else @@ -156,7 +171,10 @@ PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) { #else bool AFLCoverage::runOnModule(Module &M) { #endif - if (Ctx && DumpCFG) FATAL("Does not support dumping CFG with full context sensitive coverage enabled."); + if (Ctx && DumpCFG) + FATAL( + "Does not support dumping CFG with full context sensitive coverage " + "enabled."); LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); @@ -165,7 +183,7 @@ bool AFLCoverage::runOnModule(Module &M) { IntegerType *IntLocTy = IntegerType::getIntNTy(C, sizeof(prev_loc_t) * CHAR_BIT); #endif - uint32_t rand_seed; + uint32_t rand_seed; unsigned int cur_loc = 0; #ifdef USE_NEW_PM @@ -205,10 +223,10 @@ bool AFLCoverage::runOnModule(Module &M) { VectorType *PrevLocTy = NULL; if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX)) - FATAL( - "Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX " - "(%u))", - NGRAM_SIZE_MAX); + FATAL( + "Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX " + "(%u))", + NGRAM_SIZE_MAX); if (Ngram) PrevLocSize = Ngram - 1; @@ -219,22 +237,20 @@ bool AFLCoverage::runOnModule(Module &M) { VectorType *PrevCallerTy = NULL; if (CtxK > CTX_MAX_K) - FATAL("Bad value of K for K-context sensitivity (must be between 1 and CTX_MAX_K (%u))", - CTX_MAX_K); + FATAL( + "Bad value of K for K-context sensitivity (must be between 1 and " + "CTX_MAX_K (%u))", + CTX_MAX_K); if (CtxK == 1) { - CtxK = 0; instrument_ctx = true; instrument_caller = true; // Enable CALLER instead - } if (CtxK) { - PrevCallerSize = CtxK; instrument_ctx = true; - } #else @@ -371,11 +387,10 @@ bool AFLCoverage::runOnModule(Module &M) { Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle); - Constant * PrevCallerShuffleMask = NULL; + Constant *PrevCallerShuffleMask = NULL; SmallVector PrevCallerShuffle = {UndefValue::get(Int32Ty)}; if (CtxK) { - for (unsigned I = 0; I < PrevCallerSize - 1; ++I) PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, I)); @@ -383,7 +398,6 @@ bool AFLCoverage::runOnModule(Module &M) { PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, PrevCallerSize)); PrevCallerShuffleMask = ConstantVector::get(PrevCallerShuffle); - } #endif @@ -391,7 +405,7 @@ bool AFLCoverage::runOnModule(Module &M) { // other constants we need ConstantInt *One = ConstantInt::get(Int8Ty, 1); - Value * PrevCtx = NULL; // CTX sensitive coverage + Value *PrevCtx = NULL; // CTX sensitive coverage LoadInst *PrevCaller = NULL; // K-CTX coverage /* Instrument all the things! */ @@ -400,7 +414,6 @@ bool AFLCoverage::runOnModule(Module &M) { // scanForDangerousFunctions(&M); for (auto &F : M) { - int has_calls = 0; if (Debug) fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), @@ -413,16 +426,13 @@ bool AFLCoverage::runOnModule(Module &M) { std::list todo; for (auto &BB : F) { - BasicBlock::iterator IP = BB.getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); // Context sensitive coverage if (instrument_ctx && &BB == &F.getEntryBlock()) { - #ifdef HAVE_VECTOR_INTRINSICS if (CtxK) { - PrevCaller = IRB.CreateLoad(AFLPrevCaller); PrevCaller->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); @@ -430,7 +440,6 @@ bool AFLCoverage::runOnModule(Module &M) { IRB.CreateZExt(IRB.CreateXorReduce(PrevCaller), IRB.getInt32Ty()); } else - #endif { @@ -440,42 +449,31 @@ bool AFLCoverage::runOnModule(Module &M) { PrevCtxLoad->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); PrevCtx = PrevCtxLoad; - } // does the function have calls? and is any of the calls larger than one // basic block? for (auto &BB_2 : F) { - if (has_calls) break; for (auto &IN : BB_2) { - CallInst *callInst = nullptr; if ((callInst = dyn_cast(&IN))) { - Function *Callee = callInst->getCalledFunction(); if (!Callee || Callee->size() < function_minimum_size) continue; else { - has_calls = 1; break; - } - } - } - } // if yes we store a context ID for this function in the global var if (has_calls) { - Value *NewCtx = ConstantInt::get(Int32Ty, RandBelow(map_size)); #ifdef HAVE_VECTOR_INTRINSICS if (CtxK) { - Value *ShuffledPrevCaller = IRB.CreateShuffleVector( PrevCaller, UndefValue::get(PrevCallerTy), PrevCallerShuffleMask); @@ -488,7 +486,6 @@ bool AFLCoverage::runOnModule(Module &M) { MDNode::get(C, None)); } else - #endif { @@ -496,11 +493,8 @@ bool AFLCoverage::runOnModule(Module &M) { StoreInst *StoreCtx = IRB.CreateStore(NewCtx, AFLContext); StoreCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } - } - } if (RandBelow(100) >= InstRatio) continue; @@ -523,7 +517,6 @@ bool AFLCoverage::runOnModule(Module &M) { // fprintf(stderr, "BB %u: ", cur_loc); for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); PI != E; ++PI) { - BasicBlock *Pred = *PI; int count = 0; @@ -532,30 +525,24 @@ bool AFLCoverage::runOnModule(Module &M) { for (succ_iterator SI = succ_begin(Pred), E = succ_end(Pred); SI != E; ++SI) { - BasicBlock *Succ = *SI; // if (count > 0) // fprintf(stderr, "|"); if (Succ != NULL) count++; // fprintf(stderr, "%p", Succ); - } if (count > 1) more_than_one = 1; - } // fprintf(stderr, " == %d\n", more_than_one); if (F.size() > 1 && more_than_one != 1) { - // in CTX mode we have to restore the original context for the caller - // she might be calling other functions which need the correct CTX if (instrument_ctx && has_calls) { - Instruction *Inst = BB.getTerminator(); if (isa(Inst) || isa(Inst)) { - IRBuilder<> Post_IRB(Inst); StoreInst *RestoreCtx; @@ -567,13 +554,10 @@ bool AFLCoverage::runOnModule(Module &M) { RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } - } continue; - } #endif @@ -630,23 +614,23 @@ bool AFLCoverage::runOnModule(Module &M) { /* Update bitmap */ - if (ThreadSafe) { /* Atomic */ - /* - #if LLVM_VERSION_MAJOR < 9 - if (neverZero_counters_str != - NULL) { // with llvm 9 we make this the default as the bug - in llvm - // is then fixed - #else - if (NotZero) { - - #endif - // register MapPtrIdx in a todo list - todo.push_back(MapPtrIdx); - - } else { - - */ + if (ThreadSafe) { /* Atomic */ + /* + #if LLVM_VERSION_MAJOR < 9 + if (neverZero_counters_str != + NULL) { // with llvm 9 we make this the default as the bug + in llvm + // is then fixed + #else + if (NotZero) { + + #endif + // register MapPtrIdx in a todo list + todo.push_back(MapPtrIdx); + + } else { + + */ IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, #if LLVM_VERSION_MAJOR >= 13 llvm::MaybeAlign(1), @@ -659,7 +643,6 @@ bool AFLCoverage::runOnModule(Module &M) { */ } else { - LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); @@ -688,13 +671,12 @@ bool AFLCoverage::runOnModule(Module &M) { auto cf = IRB.CreateICmpEQ(Incr, Zero); auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); - } IRB.CreateStore(Incr, MapPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } /* non atomic case */ + } /* non atomic case */ /* Update prev_loc history vector (by placing cur_loc at the head of the vector and shuffle the other elements back by one) */ @@ -703,7 +685,6 @@ bool AFLCoverage::runOnModule(Module &M) { #ifdef HAVE_VECTOR_INTRINSICS if (Ngram) { - Value *ShuffledPrevLoc = IRB.CreateShuffleVector( PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask); Value *UpdatedPrevLoc = IRB.CreateInsertElement( @@ -713,24 +694,20 @@ bool AFLCoverage::runOnModule(Module &M) { Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); } else - #endif { Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } // in CTX mode we have to restore the original context for the caller - // she might be calling other functions which need the correct CTX. // Currently this is only needed for the Ubuntu clang-6.0 bug if (instrument_ctx && has_calls) { - Instruction *Inst = BB.getTerminator(); if (isa(Inst) || isa(Inst)) { - IRBuilder<> Post_IRB(Inst); StoreInst *RestoreCtx; @@ -742,39 +719,37 @@ bool AFLCoverage::runOnModule(Module &M) { RestoreCtx = Post_IRB.CreateStore(PrevCtx, AFLContext); RestoreCtx->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - } - } inst_blocks++; - } - } if (DumpCFG) { int fd; - if ((fd = open(DumpCFGPath.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0) + if ((fd = open(DumpCFGPath.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644)) < + 0) FATAL("Could not open/create CFG dump file."); std::string cfg = ""; for (auto record = entry_bb.begin(); record != entry_bb.end(); record++) { // Dump function BB entry points - cfg += formatv("$${0}+{1}\n", record->getFirst(), bb_to_cur_loc[record->getSecond()]); + cfg += formatv("$${0}+{1}\n", record->getFirst(), + bb_to_cur_loc[record->getSecond()]); } - for (auto record = bb_to_cur_loc.begin(); record != bb_to_cur_loc.end(); record++) { + for (auto record = bb_to_cur_loc.begin(); record != bb_to_cur_loc.end(); + record++) { // Dump CFG information - auto current_bb = record->getFirst(); - Function* calling_func = current_bb->getParent(); + auto current_bb = record->getFirst(); + Function *calling_func = current_bb->getParent(); if (calling_func) { auto function_name = calling_func->getName().str(); cfg += formatv("%%{0}", function_name); - } - else + } else cfg += "%%__"; auto current_cur_loc = record->getSecond(); cfg += formatv("+{0}\n", current_cur_loc); for (auto bb_successor = succ_begin(current_bb); - bb_successor != succ_end(current_bb); bb_successor++) { + bb_successor != succ_end(current_bb); bb_successor++) { cfg += formatv("->{0}\n", bb_to_cur_loc[*bb_successor]).str(); } } @@ -804,14 +779,13 @@ bool AFLCoverage::runOnModule(Module &M) { } }*/ - - if (Debug) { + if (Debug) { if (!inst_blocks) fprintf(stderr, "No instrumentation targets found.\n"); else - fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, (unsigned)InstRatio); - + fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, + (unsigned)InstRatio); } #ifdef USE_NEW_PM @@ -819,15 +793,12 @@ bool AFLCoverage::runOnModule(Module &M) { #else return true; #endif - } #ifndef USE_NEW_PM static void registerAFLPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { - PM.add(new AFLCoverage()); - } static RegisterStandardPasses RegisterAFLPass( diff --git a/libafl_cc/src/autotokens-pass.cc b/libafl_cc/src/autotokens-pass.cc index f8ee08573c..22873b76b2 100644 --- a/libafl_cc/src/autotokens-pass.cc +++ b/libafl_cc/src/autotokens-pass.cc @@ -64,12 +64,11 @@ #include -#define FATAL(x...) \ - do { \ - \ - fprintf(stderr, "FATAL: " x); \ - exit(1); \ - \ +#define FATAL(x...) \ + do { \ + fprintf(stderr, "FATAL: " x); \ + exit(1); \ + \ } while (0) using namespace llvm; @@ -79,7 +78,6 @@ namespace { /* Function that we never instrument or analyze */ /* Note: this ignore check is also called in isInInstrumentList() */ bool isIgnoreFunction(const llvm::Function *F) { - // Starting from "LLVMFuzzer" these are functions used in libfuzzer based // fuzzing campaign installations, e.g. oss-fuzz @@ -117,9 +115,7 @@ bool isIgnoreFunction(const llvm::Function *F) { }; for (auto const &ignoreListFunc : ignoreList) { - if (F->getName().startswith(ignoreListFunc)) { return true; } - } static constexpr const char *ignoreSubstringList[] = { @@ -131,67 +127,51 @@ bool isIgnoreFunction(const llvm::Function *F) { }; for (auto const &ignoreListFunc : ignoreSubstringList) { - // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0 if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; } - } return false; - } class AutoTokensPass : public ModulePass { - public: static char ID; AutoTokensPass() : ModulePass(ID) { - - } bool runOnModule(Module &M) override; - protected: - - private: - std::vector dictionary; - + protected: + private: + std::vector dictionary; }; } // namespace char AutoTokensPass::ID = 0; - void dict2file(int fd, uint8_t *mem, uint32_t len) { - uint32_t i, j, binary = 0; - char line[MAX_AUTO_EXTRA * 8], tmp[8]; + uint32_t i, j, binary = 0; + char line[MAX_AUTO_EXTRA * 8], tmp[8]; strcpy(line, "\""); j = 1; for (i = 0; i < len; i++) { - if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') { - line[j++] = mem[i]; } else { - if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) { - line[j] = 0; sprintf(tmp, "\\x%02x", (uint8_t)mem[i]); strcat(line, tmp); j = strlen(line); - } binary = 1; - } - } line[j] = 0; @@ -199,15 +179,13 @@ void dict2file(int fd, uint8_t *mem, uint32_t len) { if (write(fd, line, strlen(line)) <= 0) FATAL("Could not write to dictionary file"); fsync(fd); - } bool AutoTokensPass::runOnModule(Module &M) { - DenseMap valueMap; - char * ptr; + char *ptr; int fd, found = 0; - bool use_file = true; + bool use_file = true; /* Show a banner */ setvbuf(stdout, NULL, _IONBF, 0); @@ -215,22 +193,21 @@ bool AutoTokensPass::runOnModule(Module &M) { ptr = getenv("AFL_LLVM_DICT2FILE"); if (!ptr || *ptr != '/') { - // fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path: %s\n", ptr); - // fprintf(stderr, "Writing tokens into libafl_tokens section\n"); + // fprintf(stderr, "AFL_LLVM_DICT2FILE is not set to an absolute path: + // %s\n", ptr); fprintf(stderr, "Writing tokens into libafl_tokens + // section\n"); use_file = false; } - if(use_file) { + if (use_file) { if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0) FATAL("Could not open/create %s.", ptr); } - /* Instrument all the things! */ for (auto &F : M) { - if (isIgnoreFunction(&F)) continue; /* Some implementation notes. @@ -262,15 +239,12 @@ bool AutoTokensPass::runOnModule(Module &M) { */ for (auto &BB : F) { - for (auto &IN : BB) { - CallInst *callInst = nullptr; - CmpInst * cmpInst = nullptr; + CmpInst *cmpInst = nullptr; if ((cmpInst = dyn_cast(&IN))) { - - Value * op = cmpInst->getOperand(1); + Value *op = cmpInst->getOperand(1); ConstantInt *ilen = dyn_cast(op); /* We skip > 64 bit integers. why? first because their value is @@ -278,18 +252,15 @@ bool AutoTokensPass::runOnModule(Module &M) { literals > 64 bit (as of llvm 12) */ if (ilen && ilen->uge(0xffffffffffffffff) == false) { - uint64_t val2 = 0, val = ilen->getZExtValue(); uint32_t len = 0; if (val > 0x10000 && val < 0xffffffff) len = 4; if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8; if (len) { - auto c = cmpInst->getPredicate(); switch (c) { - case CmpInst::FCMP_OGT: // fall through case CmpInst::FCMP_OLE: // fall through case CmpInst::ICMP_SLE: // fall through @@ -298,10 +269,8 @@ bool AutoTokensPass::runOnModule(Module &M) { // signed comparison and it is a negative constant if ((len == 4 && (val & 80000000)) || (len == 8 && (val & 8000000000000000))) { - if ((val & 0xffff) != 1) val2 = val - 1; break; - } // fall through @@ -321,10 +290,8 @@ bool AutoTokensPass::runOnModule(Module &M) { // signed comparison and it is a negative constant if ((len == 4 && (val & 80000000)) || (len == 8 && (val & 8000000000000000))) { - if ((val & 0xffff) != 1) val2 = val - 1; break; - } // fall through @@ -338,37 +305,28 @@ bool AutoTokensPass::runOnModule(Module &M) { default: val2 = 0; - } - if(use_file) { + if (use_file) { dict2file(fd, (uint8_t *)&val, len); - } - else{ + } else { dictionary.push_back(std::string((char *)&val, len)); } found++; if (val2) { - - if(use_file) { + if (use_file) { dict2file(fd, (uint8_t *)&val2, len); - } - else{ + } else { dictionary.push_back(std::string((char *)&val2, len)); } found++; - } - } - } - } if ((callInst = dyn_cast(&IN))) { - bool isStrcmp = true; bool isMemcmp = true; bool isStrncmp = true; @@ -448,138 +406,96 @@ bool AutoTokensPass::runOnModule(Module &M) { getConstantStringInfo(Str1P, TmpStr); if (TmpStr.empty()) { - HasStr1 = false; } else { - HasStr1 = true; Str1 = TmpStr.str(); - } bool HasStr2; getConstantStringInfo(Str2P, TmpStr); if (TmpStr.empty()) { - HasStr2 = false; } else { - HasStr2 = true; Str2 = TmpStr.str(); - } // we handle the 2nd parameter first because of llvm memcpy if (!HasStr2) { - auto *Ptr = dyn_cast(Str2P); if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { - if (auto *Var = dyn_cast(Ptr->getOperand(0))) { - if (Var->hasInitializer()) { - if (auto *Array = dyn_cast(Var->getInitializer())) { - HasStr2 = true; Str2 = Array->getRawDataValues().str(); - } - } - } - } - } // for the internal memcpy routine we only care for the second // parameter and are not reporting anything. if (isIntMemcpy == true) { - if (HasStr2 == true) { - - Value * op2 = callInst->getArgOperand(2); + Value *op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast(op2); if (ilen) { - uint64_t literalLength = Str2.length(); uint64_t optLength = ilen->getZExtValue(); if (literalLength + 1 == optLength) { - Str2.append("\0", 1); // add null byte - } if (optLength > Str2.length()) { optLength = Str2.length(); } - } valueMap[Str1P] = new std::string(Str2); continue; - } continue; - } // Neither a literal nor a global variable? // maybe it is a local variable that we saved if (!HasStr2) { - std::string *strng = valueMap[Str2P]; if (strng && !strng->empty()) { - Str2 = *strng; HasStr2 = true; - } - } if (!HasStr1) { - auto Ptr = dyn_cast(Str1P); if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { - if (auto *Var = dyn_cast(Ptr->getOperand(0))) { - if (Var->hasInitializer()) { - if (auto *Array = dyn_cast(Var->getInitializer())) { - HasStr1 = true; Str1 = Array->getRawDataValues().str(); - } - } - } - } - } // Neither a literal nor a global variable? // maybe it is a local variable that we saved if (!HasStr1) { - std::string *strng = valueMap[Str1P]; if (strng && !strng->empty()) { - Str1 = *strng; HasStr1 = true; - } - } /* handle cases of one string is const, one string is variable */ @@ -597,12 +513,10 @@ bool AutoTokensPass::runOnModule(Module &M) { if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; } if (isMemcmp || isStrncmp || isStrncasecmp) { - - Value * op2 = callInst->getArgOperand(2); + Value *op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast(op2); if (ilen) { - uint64_t literalLength = optLen; optLen = ilen->getZExtValue(); if (optLen > thestring.length()) { optLen = thestring.length(); } @@ -610,33 +524,24 @@ bool AutoTokensPass::runOnModule(Module &M) { if (literalLength + 1 == optLen) { // add null byte thestring.append("\0", 1); addedNull = true; - } - } - } // add null byte if this is a string compare function and a null // was not already added if (!isMemcmp) { - if (addedNull == false && thestring[optLen - 1] != '\0') { - thestring.append("\0", 1); // add null byte optLen++; - } if (!isStdString) { - // ensure we do not have garbage size_t offset = thestring.find('\0', 0); if (offset + 1 < optLen) optLen = offset + 1; thestring = thestring.substr(0, optLen); - } - } // we take the longer string, even if the compare was to a @@ -650,85 +555,70 @@ bool AutoTokensPass::runOnModule(Module &M) { ptr = (char *)thestring.c_str(); - if(use_file){ + if (use_file) { dict2file(fd, (uint8_t *)ptr, optLen); - } - else{ + } else { dictionary.push_back(thestring.substr(0, optLen)); } found++; - } - } - } - } - if(use_file){ + if (use_file) { close(fd); return true; } LLVMContext &Ctx = M.getContext(); - if (dictionary.size()) { + size_t memlen = 0, count = 0, offset = 0; - size_t memlen = 0, count = 0, offset = 0; + // sort and unique the dictionary + std::sort(dictionary.begin(), dictionary.end()); + auto last = std::unique(dictionary.begin(), dictionary.end()); + dictionary.erase(last, dictionary.end()); - // sort and unique the dictionary - std::sort(dictionary.begin(), dictionary.end()); - auto last = std::unique(dictionary.begin(), dictionary.end()); - dictionary.erase(last, dictionary.end()); + for (auto token : dictionary) { + memlen += token.length(); + count++; + } - for (auto token : dictionary) { + auto ptrhld = std::unique_ptr(new char[memlen + count]); - memlen += token.length(); + count = 0; + + for (auto token : dictionary) { + if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) { + // This lenght is guranteed to be < MAX_AUTO_EXTRA + ptrhld.get()[offset++] = (uint8_t)token.length(); + memcpy(ptrhld.get() + offset, token.c_str(), token.length()); + offset += token.length(); count++; - - } - if (count) { - - auto ptrhld = std::unique_ptr(new char[memlen + count]); - - count = 0; - - for (auto token : dictionary) { - - if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) { - - // This lenght is guranteed to be < MAX_AUTO_EXTRA - ptrhld.get()[offset++] = (uint8_t)token.length(); - memcpy(ptrhld.get() + offset, token.c_str(), token.length()); - offset += token.length(); - count++; - } - } - - // Type - ArrayType* arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset); - - // The actual dict - GlobalVariable *dict = new GlobalVariable(M, arrayTy, true, GlobalVariable::ExternalLinkage, ConstantDataArray::get(Ctx, *(new ArrayRef(ptrhld.get(), offset))), "libafl_dictionary_" + M.getName()); - dict->setSection("libafl_token"); } } + // Type + ArrayType *arrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset); + // The actual dict + GlobalVariable *dict = new GlobalVariable( + M, arrayTy, true, GlobalVariable::ExternalLinkage, + ConstantDataArray::get(Ctx, *(new ArrayRef(ptrhld.get(), offset))), + "libafl_dictionary_" + M.getName()); + dict->setSection("libafl_token"); + return true; } - static void registerAutoTokensPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { - + legacy::PassManagerBase &PM) { PM.add(new AutoTokensPass()); - } static RegisterPass X("autotokens", - "autotokens instrumentation pass", - false, false); + "autotokens instrumentation pass", false, + false); static RegisterStandardPasses RegisterAutoTokensPass( PassManagerBuilder::EP_OptimizerLast, registerAutoTokensPass); diff --git a/libafl_cc/src/cmplog-routines-pass.cc b/libafl_cc/src/cmplog-routines-pass.cc index 0570b8aff5..b266e4c5b0 100644 --- a/libafl_cc/src/cmplog-routines-pass.cc +++ b/libafl_cc/src/cmplog-routines-pass.cc @@ -55,7 +55,6 @@ namespace { /* Function that we never instrument or analyze */ /* Note: this ignore check is also called in isInInstrumentList() */ bool isIgnoreFunction(const llvm::Function *F) { - // Starting from "LLVMFuzzer" these are functions used in libfuzzer based // fuzzing campaign installations, e.g. oss-fuzz @@ -93,9 +92,7 @@ bool isIgnoreFunction(const llvm::Function *F) { }; for (auto const &ignoreListFunc : ignoreList) { - if (F->getName().startswith(ignoreListFunc)) { return true; } - } static constexpr const char *ignoreSubstringList[] = { @@ -107,38 +104,32 @@ bool isIgnoreFunction(const llvm::Function *F) { }; for (auto const &ignoreListFunc : ignoreSubstringList) { - // hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0 if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; } - } return false; - } class CmpLogRoutines : public ModulePass { - public: static char ID; - CmpLogRoutines() : ModulePass(ID) {} + CmpLogRoutines() : ModulePass(ID) { + } bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR < 4 const char *getPassName() const override { - #else StringRef getPassName() const override { #endif return "cmplog routines"; - } private: bool hookRtns(Module &M); - }; } // namespace @@ -146,9 +137,8 @@ class CmpLogRoutines : public ModulePass { char CmpLogRoutines::ID = 0; bool CmpLogRoutines::hookRtns(Module &M) { - std::vector calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC; - LLVMContext & C = M.getContext(); + LLVMContext &C = M.getContext(); Type *VoidTy = Type::getVoidTy(C); // PointerType *VoidPtrTy = PointerType::get(VoidTy, 0); @@ -246,17 +236,13 @@ bool CmpLogRoutines::hookRtns(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - if (isIgnoreFunction(&F)) continue; for (auto &BB : F) { - for (auto &IN : BB) { - CallInst *callInst = nullptr; if ((callInst = dyn_cast(&IN))) { - Function *Callee = callInst->getCalledFunction(); if (!Callee) continue; if (callInst->getCallingConv() != llvm::CallingConv::C) continue; @@ -316,9 +302,7 @@ bool CmpLogRoutines::hookRtns(Module &M) { if (isGccStdStringCString || isGccStdStringStdString || isLlvmStdStringStdString || isLlvmStdStringCString) { - isPtrRtn = false; - } if (isPtrRtn) { calls.push_back(callInst); } @@ -326,13 +310,9 @@ bool CmpLogRoutines::hookRtns(Module &M) { if (isGccStdStringCString) { gccStdC.push_back(callInst); } if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); } if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); } - } - } - } - } if (!calls.size() && !gccStdStd.size() && !gccStdC.size() && @@ -340,119 +320,104 @@ bool CmpLogRoutines::hookRtns(Module &M) { return false; for (auto &callInst : calls) { - Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); std::vector args; - Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); - Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogHookFn, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; - } for (auto &callInst : gccStdStd) { - Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); std::vector args; - Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); - Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogGccStdStd, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; - } for (auto &callInst : gccStdC) { - Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); std::vector args; - Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); - Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogGccStdC, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; - } for (auto &callInst : llvmStdStd) { - Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); std::vector args; - Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); - Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogLlvmStdStd, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; - } for (auto &callInst : llvmStdC) { - Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1); IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); std::vector args; - Value * v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); - Value * v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); + Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); + Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); args.push_back(v1Pcasted); args.push_back(v2Pcasted); IRB.CreateCall(cmplogLlvmStdC, args); // errs() << callInst->getCalledFunction()->getName() << "\n"; - } return true; - } bool CmpLogRoutines::runOnModule(Module &M) { - hookRtns(M); verifyModule(M); return true; - } static void registerCmpLogRoutinesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { - auto p = new CmpLogRoutines(); PM.add(p); - } static RegisterStandardPasses RegisterCmpLogRoutinesPass( @@ -466,4 +431,3 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogRoutinesPass); #endif - diff --git a/libafl_cc/src/coverage-accounting-pass.cc b/libafl_cc/src/coverage-accounting-pass.cc index 2ca27ef106..aeb7f79bfe 100644 --- a/libafl_cc/src/coverage-accounting-pass.cc +++ b/libafl_cc/src/coverage-accounting-pass.cc @@ -54,59 +54,52 @@ typedef uint32_t prev_loc_t; #define MAP_SIZE LIBAFL_ACCOUNTING_MAP_SIZE - -#define SECURITY_SENSITIVE_FUNCS(CF) static CF securitySensitiveFunctions[] = {\ - CF("memcpy"), \ - CF("strlen"), \ - CF("ReadImage"), \ - CF("memmove"), \ - CF("free"), \ - CF("memset"), \ - CF("delete"), \ - CF("memcmp"), \ - CF("getString"), \ - CF("vsprintf"), \ - CF("GET_COLOR"), \ - CF("read"), \ - CF("load_bmp"), \ - CF("huffcode"), \ - CF("strcmp"), \ - CF("new"), \ - CF("getName"), \ - CF("strncat"), \ - CF("png_load"), \ -}; - +#define SECURITY_SENSITIVE_FUNCS(CF) \ + static CF securitySensitiveFunctions[] = { \ + CF("memcpy"), CF("strlen"), CF("ReadImage"), CF("memmove"), \ + CF("free"), CF("memset"), CF("delete"), CF("memcmp"), \ + CF("getString"), CF("vsprintf"), CF("GET_COLOR"), CF("read"), \ + CF("load_bmp"), CF("huffcode"), CF("strcmp"), CF("new"), \ + CF("getName"), CF("strncat"), CF("png_load"), \ + }; using namespace llvm; enum AccountingGranularity { - BB_GRAN, - FUNC_GRAN, - // LOOP, - UKNOWN_GRAN + BB_GRAN, + FUNC_GRAN, + // LOOP, + UKNOWN_GRAN }; -static cl::opt Debug("debug", cl::desc("Debug prints"), cl::init(false), cl::NotHidden); -static cl::opt GranularityStr("granularity", cl::desc("Granularity of accounting (BB, FUNC)"), cl::init(std::string("BB")), cl::NotHidden); -static cl::opt InstRatio("inst_ratio", cl::desc("Instrumentation ratio in percentage"), cl::init(100), cl::NotHidden); -static cl::opt ThreadSafe("thread_safe", cl::desc("Use the thread safe instrumentation"), cl::init(false), cl::NotHidden); +static cl::opt Debug("debug", cl::desc("Debug prints"), cl::init(false), + cl::NotHidden); +static cl::opt GranularityStr( + "granularity", cl::desc("Granularity of accounting (BB, FUNC)"), + cl::init(std::string("BB")), cl::NotHidden); +static cl::opt InstRatio( + "inst_ratio", cl::desc("Instrumentation ratio in percentage"), + cl::init(100), cl::NotHidden); +static cl::opt ThreadSafe("thread_safe", + cl::desc("Use the thread safe instrumentation"), + cl::init(false), cl::NotHidden); namespace { SECURITY_SENSITIVE_FUNCS(StringRef) -bool isSecuritySensitiveFunction(Function* F) { - if (!F) return 0; - auto func_name = F->getName(); - for (auto name : securitySensitiveFunctions) { - if (func_name.contains(name)) { - if (Debug) - fprintf(stderr, "Counted %s as security sensitive", func_name.str().c_str()); - return 1; - } +bool isSecuritySensitiveFunction(Function *F) { + if (!F) return 0; + auto func_name = F->getName(); + for (auto name : securitySensitiveFunctions) { + if (func_name.contains(name)) { + if (Debug) + fprintf(stderr, "Counted %s as security sensitive", + func_name.str().c_str()); + return 1; } - return 0; + } + return 0; } #ifdef USE_NEW_PM @@ -120,11 +113,10 @@ class AFLCoverage : public ModulePass { AFLCoverage() : ModulePass(ID) { #endif granularity = StringSwitch(GranularityStr) - .Case("BB", BB_GRAN) - .Case("FUNC", FUNC_GRAN) - .Default(UKNOWN_GRAN); + .Case("BB", BB_GRAN) + .Case("FUNC", FUNC_GRAN) + .Default(UKNOWN_GRAN); // initInstrumentList(); - } #ifdef USE_NEW_PM @@ -134,10 +126,9 @@ class AFLCoverage : public ModulePass { #endif protected: - uint32_t map_size = MAP_SIZE; - uint32_t function_minimum_size = 1; + uint32_t map_size = MAP_SIZE; + uint32_t function_minimum_size = 1; AccountingGranularity granularity; - }; } // namespace @@ -145,33 +136,30 @@ class AFLCoverage : public ModulePass { #ifdef USE_NEW_PM extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { - return { - LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { -#if 1 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - MPM.addPass(AFLCoverage()); - } - ); -/* TODO LTO registration */ -#else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback( - [](StringRef Name, ModulePassManager &MPM, ArrayRef) { - if ( Name == "AFLCoverageAccounting" ) { - MPM.addPass(AFLCoverage()); - return true; - } else { - return false; - } - } - ); -#endif - } - }; + return {LLVM_PLUGIN_API_VERSION, "AFLCoverageAccounting", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + #if 1 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + MPM.addPass(AFLCoverage()); + }); + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + if (Name == "AFLCoverageAccounting") { + MPM.addPass(AFLCoverage()); + return true; + } else { + return false; + } + }); + #endif + }}; } #else @@ -187,7 +175,7 @@ bool AFLCoverage::runOnModule(Module &M) { LLVMContext &C = M.getContext(); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); - uint32_t rand_seed; + uint32_t rand_seed; unsigned int cur_loc = 0; #ifdef USE_NEW_PM @@ -206,19 +194,19 @@ bool AFLCoverage::runOnModule(Module &M) { /* Get globals for the SHM region and the previous location. Note that __afl_acc_prev_loc is thread-local. */ - GlobalVariable *AFLMemOpPtr = - new GlobalVariable(M, PointerType::get(Int32Ty, 0), false, - GlobalValue::ExternalLinkage, 0, "__afl_acc_memop_ptr"); + GlobalVariable *AFLMemOpPtr = new GlobalVariable( + M, PointerType::get(Int32Ty, 0), false, GlobalValue::ExternalLinkage, 0, + "__afl_acc_memop_ptr"); GlobalVariable *AFLPrevLoc; #if defined(__ANDROID__) || defined(__HAIKU__) - AFLPrevLoc = new GlobalVariable( - M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc"); + AFLPrevLoc = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc"); #else AFLPrevLoc = new GlobalVariable( - M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc", 0, - GlobalVariable::GeneralDynamicTLSModel, 0, false); + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_acc_prev_loc", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); #endif /* Instrument all the things! */ @@ -227,7 +215,6 @@ bool AFLCoverage::runOnModule(Module &M) { // scanForDangerousFunctions(&M); for (auto &F : M) { - int has_calls = 0; if (Debug) fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), @@ -239,7 +226,6 @@ bool AFLCoverage::runOnModule(Module &M) { std::list todo; for (auto &BB : F) { - BasicBlock::iterator IP = BB.getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); @@ -250,8 +236,7 @@ bool AFLCoverage::runOnModule(Module &M) { for (auto &I : BB) { switch (granularity) { case BB_GRAN: - if (I.mayReadFromMemory() || I.mayWriteToMemory()) - ++MemCnt; + if (I.mayReadFromMemory() || I.mayWriteToMemory()) ++MemCnt; break; case FUNC_GRAN: if (auto *C = dyn_cast(&I)) { @@ -275,36 +260,37 @@ bool AFLCoverage::runOnModule(Module &M) { /* Load SHM pointer */ LoadInst *MemReadPtr = IRB.CreateLoad(AFLMemOpPtr); - MemReadPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *MemReadPtrIdx = IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc)); + MemReadPtr->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + Value *MemReadPtrIdx = + IRB.CreateGEP(MemReadPtr, IRB.CreateXor(PrevLoc, CurLoc)); /* Update bitmap */ LoadInst *MemReadCount = IRB.CreateLoad(MemReadPtrIdx); - MemReadCount->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *MemReadIncr = IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt)); + MemReadCount->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + Value *MemReadIncr = + IRB.CreateAdd(MemReadCount, ConstantInt::get(Int32Ty, MemCnt)); IRB.CreateStore(MemReadIncr, MemReadPtrIdx) ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); /* Update prev_loc */ - StoreInst * Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), - AFLPrevLoc); + StoreInst *Store = + IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); inst_blocks++; - } - } - - if (Debug) { + if (Debug) { if (!inst_blocks) fprintf(stderr, "No instrumentation targets found.\n"); else - fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, (unsigned)InstRatio); - + fprintf(stderr, "Instrumented %d locations (ratio %u%%).\n", inst_blocks, + (unsigned)InstRatio); } #ifdef USE_NEW_PM @@ -312,15 +298,12 @@ bool AFLCoverage::runOnModule(Module &M) { #else return true; #endif - } #ifndef USE_NEW_PM static void registerAFLPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { - PM.add(new AFLCoverage()); - } static RegisterStandardPasses RegisterAFLPass(