diff options
author | van Hauser <vh@thc.org> | 2020-08-17 23:42:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-17 23:42:45 +0200 |
commit | 0a6084f3613f15d2508d43334d28e671f5c6c573 (patch) | |
tree | a58da1d2ed34cef4020c1fccbd70c4679d7e59fb /llvm_mode/afl-llvm-common.cc | |
parent | 8044ae28be2dd109ac16719ce2e304074fa74efd (diff) | |
parent | 9532499ef5280ae4c7aa3d189dd7a924a38e8358 (diff) | |
download | afl++-0a6084f3613f15d2508d43334d28e671f5c6c573.tar.gz |
Merge pull request #499 from AFLplusplus/dev
important push to stable
Diffstat (limited to 'llvm_mode/afl-llvm-common.cc')
-rw-r--r-- | llvm_mode/afl-llvm-common.cc | 357 |
1 files changed, 165 insertions, 192 deletions
diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 0b50c547..d9e63bd3 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -67,8 +67,11 @@ bool isIgnoreFunction(const llvm::Function *F) { "__libc_csu", "__asan", "__msan", + "__cmplog", + "__sancov", "msan.", "LLVMFuzzer", + "__decide_deferred", "maybe_duplicate_stderr", "discard_output", "close_stdout", @@ -253,101 +256,63 @@ void initInstrumentList() { } -bool isInInstrumentList(llvm::Function *F) { - - // is this a function with code? If it is external we dont instrument it - // anyway and cant be in the the instrument file list. Or if it is ignored. - if (!F->size() || isIgnoreFunction(F)) return false; - - // if we do not have a the instrument file list return true - if (!allowListFiles.empty() || !allowListFunctions.empty()) { - - if (!allowListFunctions.empty()) { - - std::string instFunction = F->getName().str(); - - for (std::list<std::string>::iterator it = allowListFunctions.begin(); - it != allowListFunctions.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ - - if (instFunction.length() >= it->length()) { - - if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { - - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the allow function list, " - "instrumenting ... \n", - instFunction.c_str()); - return true; - - } - - } - - } +void scanForDangerousFunctions(llvm::Module *M) { - } + if (!M) return; - if (!allowListFiles.empty()) { +#if LLVM_VERSION_MAJOR > 3 || \ + (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 9) - // let's try to get the filename for the function - auto bb = &F->getEntryBlock(); - BasicBlock::iterator IP = bb->getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - DebugLoc Loc = IP->getDebugLoc(); + for (GlobalIFunc &IF : M->ifuncs()) { -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { + StringRef ifunc_name = IF.getName(); + Constant *r = IF.getResolver(); + StringRef r_name = cast<Function>(r->getOperand(0))->getName(); + if (!be_quiet) + fprintf(stderr, + "Info: Found an ifunc with name %s that points to resolver " + "function %s, we will not instrument this, putting it into the " + "block list.\n", + ifunc_name.str().c_str(), r_name.str().c_str()); + denyListFunctions.push_back(r_name.str()); - DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); + } - if (instFilename.str().empty()) { + GlobalVariable *GV = M->getNamedGlobal("llvm.global_ctors"); + if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) { - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { + ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); + if (InitList) { - } + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - } + if (ConstantStruct *CS = + dyn_cast<ConstantStruct>(InitList->getOperand(i))) { - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { + if (CS->getNumOperands() >= 2) { - for (std::list<std::string>::iterator it = allowListFiles.begin(); - it != allowListFiles.end(); ++it) { + if (CS->getOperand(1)->isNullValue()) + break; // Found a null terminator, stop here. - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0)); + int Priority = CI ? CI->getSExtValue() : 0; - if (instFilename.str().length() >= it->length()) { + Constant *FP = CS->getOperand(1); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) + if (CE->isCast()) FP = CE->getOperand(0); + if (Function *F = dyn_cast<Function>(FP)) { - if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == - 0) { + if (!F->isDeclaration() && + strncmp(F->getName().str().c_str(), "__afl", 5) != 0) { - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the allowlist (%s), " - "instrumenting ... \n", - F->getName().str().c_str(), instFilename.str().c_str()); - return true; + if (!be_quiet) + fprintf(stderr, + "Info: Found constructor function %s with prio " + "%u, we will not instrument this, putting it into a " + "block list.\n", + F->getName().str().c_str(), Priority); + denyListFunctions.push_back(F->getName().str()); } @@ -361,63 +326,67 @@ bool isInInstrumentList(llvm::Function *F) { } -#else - if (!Loc.isUnknown()) { + } - DILocation cDILoc(Loc.getAsMDNode(F->getContext())); +#endif - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); +} - (void)instLine; - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { +static std::string getSourceName(llvm::Function *F) { - for (std::list<std::string>::iterator it = allowListFiles.begin(); - it != allowListFiles.end(); ++it) { + // let's try to get the filename for the function + auto bb = &F->getEntryBlock(); + BasicBlock::iterator IP = bb->getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); + DebugLoc Loc = IP->getDebugLoc(); - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ +#if LLVM_VERSION_MAJOR >= 4 || \ + (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) + if (Loc) { - if (instFilename.str().length() >= it->length()) { + DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode()); - if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == - 0) { + StringRef instFilename = cDILoc->getFilename(); - return true; + if (instFilename.str().empty()) { - } + /* If the original location is empty, try using the inlined location + */ + DILocation *oDILoc = cDILoc->getInlinedAt(); + if (oDILoc) { instFilename = oDILoc->getFilename(); } - } + } - } + return instFilename.str(); - } + } - } +#else + if (!Loc.isUnknown()) { - } + DILocation cDILoc(Loc.getAsMDNode(F->getContext())); + + StringRef instFilename = cDILoc.getFilename(); + + /* Continue only if we know where we actually are */ + return instFilename.str(); + + } #endif - else { - // we could not find out the location. in this case we say it is not - // in the the instrument file list - if (!be_quiet) - WARNF( - "No debug information found for function %s, will not be " - "instrumented (recompile with -g -O[1-3]).", - F->getName().str().c_str()); - return false; + return std::string(""); - } +} - return false; +bool isInInstrumentList(llvm::Function *F) { - } + bool return_default = true; + + // is this a function with code? If it is external we don't instrument it + // anyway and it can't be in the instrument file list. Or if it is it is + // ignored. + if (!F->size() || isIgnoreFunction(F)) return false; if (!denyListFiles.empty() || !denyListFunctions.empty()) { @@ -455,62 +424,75 @@ bool isInInstrumentList(llvm::Function *F) { if (!denyListFiles.empty()) { - // let's try to get the filename for the function - auto bb = &F->getEntryBlock(); - BasicBlock::iterator IP = bb->getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - DebugLoc Loc = IP->getDebugLoc(); + std::string source_file = getSourceName(F); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { + if (!source_file.empty()) { - DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode()); + for (std::list<std::string>::iterator it = denyListFiles.begin(); + it != denyListFiles.end(); ++it) { - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (instFilename.str().empty()) { + if (source_file.length() >= it->length()) { - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { + if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); + return false; + + } } } - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { + } else { - for (std::list<std::string>::iterator it = denyListFiles.begin(); - it != denyListFiles.end(); ++it) { + // we could not find out the location. in this case we say it is not + // in the instrument file list + if (!be_quiet) + WARNF( + "No debug information found for function %s, will be " + "instrumented (recompile with -g -O[1-3]).", + F->getName().str().c_str()); - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + } - if (instFilename.str().length() >= it->length()) { + } - if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == - 0) { + } - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the denylist (%s), not " - "instrumenting ... \n", - F->getName().str().c_str(), instFilename.str().c_str()); - return false; + // if we do not have a instrument file list return true + if (!allowListFiles.empty() || !allowListFunctions.empty()) { - } + return_default = false; - } + if (!allowListFunctions.empty()) { + + std::string instFunction = F->getName().str(); + + for (std::list<std::string>::iterator it = allowListFunctions.begin(); + it != allowListFunctions.end(); ++it) { + + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ + + if (instFunction.length() >= it->length()) { + + if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { + + if (debug) + SAYF(cMGN "[D] " cRST + "Function %s is in the allow function list, " + "instrumenting ... \n", + instFunction.c_str()); + return true; } @@ -520,35 +502,31 @@ bool isInInstrumentList(llvm::Function *F) { } -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(F->getContext())); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); + if (!allowListFiles.empty()) { - (void)instLine; - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { + std::string source_file = getSourceName(F); - for (std::list<std::string>::iterator it = denyListFiles.begin(); - it != denyListFiles.end(); ++it) { + if (!source_file.empty()) { - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + for (std::list<std::string>::iterator it = allowListFiles.begin(); + it != allowListFiles.end(); ++it) { - if (instFilename.str().length() >= it->length()) { + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == - 0) { + if (source_file.length() >= it->length()) { - return false; + if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { - } + if (debug) + SAYF(cMGN "[D] " cRST + "Function %s is in the allowlist (%s), " + "instrumenting ... \n", + F->getName().str().c_str(), source_file.c_str()); + return true; } @@ -556,29 +534,24 @@ bool isInInstrumentList(llvm::Function *F) { } - } + } else { - } + // we could not find out the location. In this case we say it is not + // in the instrument file list + if (!be_quiet) + WARNF( + "No debug information found for function %s, will not be " + "instrumented (recompile with -g -O[1-3]).", + F->getName().str().c_str()); + return false; -#endif - else { - - // we could not find out the location. in this case we say it is not - // in the the instrument file list - if (!be_quiet) - WARNF( - "No debug information found for function %s, will be " - "instrumented (recompile with -g -O[1-3]).", - F->getName().str().c_str()); - return true; + } } - return true; - } - return true; // not reached + return return_default; } |