-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Focused taint #112215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Focused taint #112215
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A new option is added to Clang Static Analyzer that drives the symbolic execution to only analyzer those top level functions which may yield taint related findings.
…cker from the GenericTaint checker
Member
|
@llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Daniel Krupp (dkrupp) ChangesFull diff: https://github.com/llvm/llvm-project/pull/112215.diff 8 Files Affected:
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 7da0d0a87e8c0c..309d1bab74d7f5 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1048,7 +1048,6 @@ def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
} // end "alpha.security"
-
//===----------------------------------------------------------------------===//
// Mac OS X, Cocoa, and Core Foundation checkers.
//===----------------------------------------------------------------------===//
@@ -1686,7 +1685,15 @@ def TaintPropagationChecker : Checker<"TaintPropagation">, // Modelling checker
"Config",
"Specifies the name of the configuration file.",
"",
+ Released>,
+ CmdLineOption<Boolean,
+ "AggressiveTaintPropagation",
+ "If set to true and if a called function cannot be inlined, "
+ "taintedness will be propagated to the return value and to non-const "
+ "reference parameters",
+ "false",
Released>
+
]>,
Documentation<NotDocumented>,
Hidden;
diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index 737bc8e86cfb6a..bab7491883396a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -412,6 +412,16 @@ ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
ANALYZER_OPTION(unsigned, MaxTaintedSymbolComplexity, "max-tainted-symbol-complexity",
"[DEPRECATED] The maximum complexity of a symbol to carry taint", 9)
+ANALYZER_OPTION(bool, AnalyzerInlineTaintOnly, "analyzer-inline-taint-only",
+ "Only inline on a call-path to a taint source or sink", false)
+
+ANALYZER_OPTION(bool, AnalyzerFocusedTaint, "analyzer-focused-taint",
+ "Only inline top-level functions on a call-path to a taint source or sink", false)
+
+ANALYZER_OPTION(bool, AnalyzerAlwaysInlineTainted, "analyzer-always-inline-tainted",
+ "Always inline taint related functions", false)
+
+
ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
"The maximum times a large function could be inlined.", 32)
diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 3a3c1a13d67dd5..0b979ecd94c9ea 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -293,6 +293,9 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
ShowConfigOptionsList(false),
ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false),
AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false),
+ AnalyzerFocusedTaint(false),
+ AnalyzerInlineTaintOnly(false),
+ AnalyzerAlwaysInlineTainted(false),
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {}
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index c76e9c0326afe7..27d23714c1ea68 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -42,6 +42,7 @@ class AnalysisManager : public BugReporterData {
ConstraintManagerCreator CreateConstraintMgr;
CheckerManager *CheckerMgr;
+ std::set<FunctionDecl*> TaintRelatedFunctions;
public:
AnalyzerOptions &options;
@@ -59,6 +60,13 @@ class AnalysisManager : public BugReporterData {
AnaCtxMgr.clear();
}
+ void setTaintRelatedFunctions(std::set<FunctionDecl*> TaintedFunctions){
+ TaintRelatedFunctions = TaintedFunctions;
+ }
+ std::set<FunctionDecl*> getTaintRelatedFunctions(){
+ return TaintRelatedFunctions;
+ }
+
AnalysisDeclContextManager& getAnalysisDeclContextManager() {
return AnaCtxMgr;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index b89a6e2588c987..85b5796cc16701 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -16,6 +16,7 @@
#include "Yaml.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Checkers/Taint.h"
@@ -26,6 +27,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"
@@ -77,6 +79,13 @@ static ArgIdxTy fromArgumentCount(unsigned Count) {
return Count;
}
+/// Handles the resolution of indexes of type ArgIdxTy to Expr*-s.
+static const Expr *GetArgExpr(ArgIdxTy ArgIdx, const CallEvent &Call) {
+ return ArgIdx == ReturnValueIndex ? Call.getOriginExpr()
+ : Call.getArgExpr(ArgIdx);
+ };
+
+
/// Check if the region the expression evaluates to is the standard input,
/// and thus, is tainted.
/// FIXME: Move this to Taint.cpp.
@@ -393,6 +402,7 @@ class GenericTaintChecker : public Checker<check::PreCall, check::PostCall> {
CheckerContext &C) const;
bool isTaintReporterCheckerEnabled = false;
+ bool AggressiveTaintPropagation = false;
std::optional<BugType> BT;
private:
@@ -854,6 +864,8 @@ void GenericTaintChecker::checkPreCall(const CallEvent &Call,
void GenericTaintChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
+
+
// Set the marked values as tainted. The return value only accessible from
// checkPostStmt.
ProgramStateRef State = C.getState();
@@ -864,7 +876,55 @@ void GenericTaintChecker::checkPostCall(const CallEvent &Call,
// stored in the state as TaintArgsOnPostVisit set.
TaintArgsOnPostVisitTy TaintArgsMap = State->get<TaintArgsOnPostVisit>();
+
+ const ArgIdxTy CallNumArgs = fromArgumentCount(Call.getNumArgs());
+
+
const ImmutableSet<ArgIdxTy> *TaintArgs = TaintArgsMap.lookup(CurrentFrame);
+ auto &F = State->getStateManager().get_context<ArgIdxFactory>();
+ ImmutableSet<ArgIdxTy> ApproxTaintedArgs = F.add(F.getEmptySet(), ReturnValueIndex);
+
+ if (!C.wasInlined && !TaintArgs) {
+ llvm::errs() << "PostCall<";
+ Call.dump(llvm::errs());
+ llvm::errs() << "Was not inlined.\n";
+ /// Check for taint sinks.
+ ProgramStateRef State = C.getState();
+ bool HasTaintedParam = false;
+ for (ArgIdxTy I = ReturnValueIndex; I < CallNumArgs; ++I) {
+ const Expr *E = GetArgExpr(I, Call);
+ if (!E)
+ continue;
+ HasTaintedParam =
+ HasTaintedParam || isTaintedOrPointsToTainted(State, C.getSVal(E));
+ }
+ llvm::errs() << "\nHasTaintedParam:" << HasTaintedParam << "\n";
+ if (HasTaintedParam && !TaintArgs && AggressiveTaintPropagation) {
+ llvm::errs() << "Making return value and writable params tainted.\n";
+ llvm::errs() << "Number of params:" << CallNumArgs;
+
+ for (ArgIdxTy I = ReturnValueIndex+1; I < CallNumArgs; ++I) {
+ const Expr *E = GetArgExpr(I, Call);
+ if (!E)
+ continue;
+ SVal ArgSVal = C.getSVal(E);
+ //checking if the argument is a non-const pointer
+ auto LValue = ArgSVal.getAs<Loc>();
+ if (!LValue)
+ continue;
+ const QualType ArgTy = LValue->getType(State->getStateManager().getContext());
+ if (ArgTy->isPointerType() && !ArgTy.isConstQualified()){
+ llvm::errs() << "Param "<< I;
+ llvm::errs() << "is a non const qualified pointer, so tainting it\n";
+ ArgTy->dump();
+ llvm::errs()<<"\n";
+ ApproxTaintedArgs = F.add(ApproxTaintedArgs, I);
+ }
+ }
+ TaintArgs = &ApproxTaintedArgs;
+ }
+ }
+
if (!TaintArgs)
return;
assert(!TaintArgs->isEmpty());
@@ -1129,6 +1189,10 @@ void GenericTaintChecker::taintUnsafeSocketProtocol(const CallEvent &Call,
/// Checker registration
void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
Mgr.registerChecker<GenericTaintChecker>();
+ GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
+ checker->AggressiveTaintPropagation =
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption(checker,
+ "AggressiveTaintPropagation");
}
bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 2ca24d0c5ab22b..ce43548b2c66a2 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -1078,6 +1078,27 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
+ bool TaintRelatedFun=false;
+
+ if (Opts.AnalyzerInlineTaintOnly) {
+ std::set<FunctionDecl*> TaintedFunctions = AMgr.getTaintRelatedFunctions();
+ // if the function is not taint related skip it.
+ auto *FD = dyn_cast<FunctionDecl>(const_cast<Decl*>(D));
+ if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
+ llvm::errs()
+ << "Skipping inlining of not taint related function from the analysis:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ return false;
+ } else {
+ TaintRelatedFun=true;
+ llvm::errs()
+ << "tyring to inline taint related function:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ //leave the other budget limits to kick in
+ //otherwise the analysis may hang
+ //return true;
+ }
+ }
// The auto-synthesized bodies are essential to inline as they are
// usually small and commonly used. Note: we should do this check early on to
// ensure we always inline these calls.
@@ -1118,14 +1139,17 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
}
// Do not inline if recursive or we've reached max stack frame count.
+ // We skip this bound if the function is taint related
bool IsRecursive = false;
unsigned StackDepth = 0;
examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
- if ((StackDepth >= Opts.InlineMaxStackDepth) &&
+ if (!(Opts.AnalyzerAlwaysInlineTainted && TaintRelatedFun && (StackDepth < 3*Opts.InlineMaxStackDepth))
+ && (StackDepth >= Opts.InlineMaxStackDepth) &&
(!isSmall(CalleeADC) || IsRecursive))
return false;
// Do not inline large functions too many times.
+ // We skip this bound if the function is taint related
if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
Opts.MaxTimesInlineLarge) &&
isLarge(CalleeADC)) {
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 03bc40804d7328..2af0654e0a5cb6 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -33,6 +33,8 @@
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include <llvm/ADT/DepthFirstIterator.h>
+#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Statistic.h"
@@ -243,6 +245,11 @@ class AnalysisConsumer : public AnalysisASTConsumer,
ExprEngine::InliningModes
getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
+
+ std::set<FunctionDecl*> getDeclsForTaintAnalysis(CallGraph &CG);
+ bool isTaintRelatedFunction(const FunctionDecl* FD);
+
+
/// Build the call graph for all the top level decls of this TU and
/// use it to define the order in which the functions should be visited.
void HandleDeclsCallGraph(const unsigned LocalTUDeclsSize);
@@ -435,16 +442,76 @@ AnalysisConsumer::getInliningModeForFunction(const Decl *D,
return ExprEngine::Inline_Regular;
}
+bool AnalysisConsumer::isTaintRelatedFunction(const FunctionDecl* FD){
+ std::set<std::string> sources = {"scanf","gets","getch","read","fopen","fdopen","freopen","getchar",
+ "gets_s","scanf_s","getcwd","readlink","gethostname","getnameinfo","readlinkat","get_current_dir_name",
+ "getseuserbyname","getgroups","getlogin","getlogin_r","popen","getenv"};
+ std::set<std::string> sinks = {"system", "execv","popen","malloc","calloc","memcpy","strcpy","strncpy"};
+ if (!FD || !FD->getCanonicalDecl())
+ return false;
+ std::string FN = FD->getCanonicalDecl()->getNameAsString();
+ //llvm::errs()<<"Inspecting function if tainted " << FN << "\n";
+ return (sources.count(FN) || sinks.count(FN));
+}
+
+// returns functions declarations required for taint analysis
+std::set<FunctionDecl*> AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG) {
+ std::set<FunctionDecl*> TaintedFunctions;
+ for (auto N = llvm::df_begin(&CG), EI = llvm::df_end(&CG); N != EI; N++) {
+ Decl *D = N->getDecl();
+ // Skip the abstract root node.
+ if (!D)
+ continue;
+
+ auto *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD)
+ continue;
+ if (FD->getDefinition()) {
+ llvm::errs() << "Visiting function: " << FD->getNameInfo().getAsString() << "\n";
+ }
+
+ for (auto Callee : N->callees()){
+ FunctionDecl *CFD = dyn_cast<FunctionDecl>(Callee.Callee->getDecl());
+ if (!CFD)
+ continue;
+ if (isTaintRelatedFunction(CFD))
+ TaintedFunctions.insert(FD);
+ if (TaintedFunctions.find(CFD)!=TaintedFunctions.end())//if child is tainted, the parent is also tainted
+ TaintedFunctions.insert(FD);
+ }
+
+
+ if (isTaintRelatedFunction(FD)){
+ llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is tainted\n";
+ TaintedFunctions.insert(FD);
+ } else
+ llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is NOT tainted\n";
+
+ }
+ return TaintedFunctions;
+}
+
void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
// Build the Call Graph by adding all the top level declarations to the graph.
// Note: CallGraph can trigger deserialization of more items from a pch
// (though HandleInterestingDecl); triggering additions to LocalTUDecls.
// We rely on random access to add the initially processed Decls to CG.
+
CallGraph CG;
for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
CG.addToCallGraph(LocalTUDecls[i]);
}
+ std::set<FunctionDecl*> TaintedFunctions;
+ if (Opts.AnalyzerFocusedTaint||Opts.AnalyzerInlineTaintOnly){
+ TaintedFunctions = getDeclsForTaintAnalysis(CG);
+ Mgr->setTaintRelatedFunctions(TaintedFunctions);
+ llvm::errs()<<"Tainted functions:\n";
+ for (FunctionDecl* FD:TaintedFunctions){
+ llvm::errs()<<FD->getNameInfo().getAsString() << "\n";
+ }
+ }
+
// Walk over all of the call graph nodes in topological order, so that we
// analyze parents before the children. Skip the functions inlined into
// the previously processed functions. Use external Visited set to identify
@@ -463,6 +530,7 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
if (!D)
continue;
+
// Skip the functions which have been processed already or previously
// inlined.
if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
@@ -480,6 +548,17 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
continue;
}
+ if (Opts.AnalyzerFocusedTaint) {
+ // if the function is not taint related skip it.
+ auto *FD = dyn_cast<FunctionDecl>(D);
+ if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
+ llvm::errs()
+ << "Skipping not taint related function from the analysis:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ continue;
+ }
+ }
+
// Analyze the function.
SetOfConstDecls VisitedCallees;
diff --git a/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
new file mode 100644
index 00000000000000..d0e1e980d62be5
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+char buf[1024];
+
+int fetchTaintedString(char *txt){
+ scanf("%s", txt);
+}
+
+int exec(char* cmd){
+ system(cmd);//warn here
+}
+
+void topLevel(){
+ char cmd[2048] = "/bin/cat ";
+ char filename[1024];
+ fetchTaintedString (filename);
+ strcat(cmd, filename);
+ exec(cmd);
+}
+
+void printNum(int data){
+ printf("Data:%d\n",data);
+}
\ No newline at end of file
|
You can test this locally with the following command:git-clang-format --diff 39babbffc9f44244efaeca8951782a2a6ef814db 470cb4bbdeaa2f5238b28966a8557d7920f21bf1 --extensions c,h,cpp -- clang/lib/StaticAnalyzer/taint_focused/taintcalls.c clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cppView the diff from clang-format here.diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 0b979ecd94..812b48d62a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -293,8 +293,7 @@ public:
ShowConfigOptionsList(false),
ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false),
AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false),
- AnalyzerFocusedTaint(false),
- AnalyzerInlineTaintOnly(false),
+ AnalyzerFocusedTaint(false), AnalyzerInlineTaintOnly(false),
AnalyzerAlwaysInlineTainted(false),
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 27d23714c1..4be764c103 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -42,7 +42,7 @@ class AnalysisManager : public BugReporterData {
ConstraintManagerCreator CreateConstraintMgr;
CheckerManager *CheckerMgr;
- std::set<FunctionDecl*> TaintRelatedFunctions;
+ std::set<FunctionDecl *> TaintRelatedFunctions;
public:
AnalyzerOptions &options;
@@ -60,10 +60,10 @@ public:
AnaCtxMgr.clear();
}
- void setTaintRelatedFunctions(std::set<FunctionDecl*> TaintedFunctions){
+ void setTaintRelatedFunctions(std::set<FunctionDecl *> TaintedFunctions) {
TaintRelatedFunctions = TaintedFunctions;
}
- std::set<FunctionDecl*> getTaintRelatedFunctions(){
+ std::set<FunctionDecl *> getTaintRelatedFunctions() {
return TaintRelatedFunctions;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 85b5796cc1..40ffda0f00 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -81,10 +81,9 @@ static ArgIdxTy fromArgumentCount(unsigned Count) {
/// Handles the resolution of indexes of type ArgIdxTy to Expr*-s.
static const Expr *GetArgExpr(ArgIdxTy ArgIdx, const CallEvent &Call) {
- return ArgIdx == ReturnValueIndex ? Call.getOriginExpr()
- : Call.getArgExpr(ArgIdx);
- };
-
+ return ArgIdx == ReturnValueIndex ? Call.getOriginExpr()
+ : Call.getArgExpr(ArgIdx);
+};
/// Check if the region the expression evaluates to is the standard input,
/// and thus, is tainted.
@@ -865,7 +864,6 @@ void GenericTaintChecker::checkPreCall(const CallEvent &Call,
void GenericTaintChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
-
// Set the marked values as tainted. The return value only accessible from
// checkPostStmt.
ProgramStateRef State = C.getState();
@@ -876,13 +874,12 @@ void GenericTaintChecker::checkPostCall(const CallEvent &Call,
// stored in the state as TaintArgsOnPostVisit set.
TaintArgsOnPostVisitTy TaintArgsMap = State->get<TaintArgsOnPostVisit>();
-
const ArgIdxTy CallNumArgs = fromArgumentCount(Call.getNumArgs());
-
const ImmutableSet<ArgIdxTy> *TaintArgs = TaintArgsMap.lookup(CurrentFrame);
auto &F = State->getStateManager().get_context<ArgIdxFactory>();
- ImmutableSet<ArgIdxTy> ApproxTaintedArgs = F.add(F.getEmptySet(), ReturnValueIndex);
+ ImmutableSet<ArgIdxTy> ApproxTaintedArgs =
+ F.add(F.getEmptySet(), ReturnValueIndex);
if (!C.wasInlined && !TaintArgs) {
llvm::errs() << "PostCall<";
@@ -903,21 +900,22 @@ void GenericTaintChecker::checkPostCall(const CallEvent &Call,
llvm::errs() << "Making return value and writable params tainted.\n";
llvm::errs() << "Number of params:" << CallNumArgs;
- for (ArgIdxTy I = ReturnValueIndex+1; I < CallNumArgs; ++I) {
+ for (ArgIdxTy I = ReturnValueIndex + 1; I < CallNumArgs; ++I) {
const Expr *E = GetArgExpr(I, Call);
if (!E)
continue;
SVal ArgSVal = C.getSVal(E);
- //checking if the argument is a non-const pointer
+ // checking if the argument is a non-const pointer
auto LValue = ArgSVal.getAs<Loc>();
if (!LValue)
continue;
- const QualType ArgTy = LValue->getType(State->getStateManager().getContext());
- if (ArgTy->isPointerType() && !ArgTy.isConstQualified()){
- llvm::errs() << "Param "<< I;
+ const QualType ArgTy =
+ LValue->getType(State->getStateManager().getContext());
+ if (ArgTy->isPointerType() && !ArgTy.isConstQualified()) {
+ llvm::errs() << "Param " << I;
llvm::errs() << "is a non const qualified pointer, so tainting it\n";
ArgTy->dump();
- llvm::errs()<<"\n";
+ llvm::errs() << "\n";
ApproxTaintedArgs = F.add(ApproxTaintedArgs, I);
}
}
@@ -1191,8 +1189,8 @@ void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
Mgr.registerChecker<GenericTaintChecker>();
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
checker->AggressiveTaintPropagation =
- Mgr.getAnalyzerOptions().getCheckerBooleanOption(checker,
- "AggressiveTaintPropagation");
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption(
+ checker, "AggressiveTaintPropagation");
}
bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index ce43548b2c..068c091c3f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -1078,26 +1078,25 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
- bool TaintRelatedFun=false;
+ bool TaintRelatedFun = false;
if (Opts.AnalyzerInlineTaintOnly) {
- std::set<FunctionDecl*> TaintedFunctions = AMgr.getTaintRelatedFunctions();
- // if the function is not taint related skip it.
- auto *FD = dyn_cast<FunctionDecl>(const_cast<Decl*>(D));
- if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
- llvm::errs()
- << "Skipping inlining of not taint related function from the analysis:\n";
- llvm::errs() << FD->getNameInfo().getAsString() << "\n";
- return false;
- } else {
- TaintRelatedFun=true;
- llvm::errs()
- << "tyring to inline taint related function:\n";
- llvm::errs() << FD->getNameInfo().getAsString() << "\n";
- //leave the other budget limits to kick in
- //otherwise the analysis may hang
- //return true;
- }
+ std::set<FunctionDecl *> TaintedFunctions = AMgr.getTaintRelatedFunctions();
+ // if the function is not taint related skip it.
+ auto *FD = dyn_cast<FunctionDecl>(const_cast<Decl *>(D));
+ if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
+ llvm::errs() << "Skipping inlining of not taint related function from "
+ "the analysis:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ return false;
+ } else {
+ TaintRelatedFun = true;
+ llvm::errs() << "tyring to inline taint related function:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ // leave the other budget limits to kick in
+ // otherwise the analysis may hang
+ // return true;
+ }
}
// The auto-synthesized bodies are essential to inline as they are
// usually small and commonly used. Note: we should do this check early on to
@@ -1143,8 +1142,9 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
bool IsRecursive = false;
unsigned StackDepth = 0;
examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
- if (!(Opts.AnalyzerAlwaysInlineTainted && TaintRelatedFun && (StackDepth < 3*Opts.InlineMaxStackDepth))
- && (StackDepth >= Opts.InlineMaxStackDepth) &&
+ if (!(Opts.AnalyzerAlwaysInlineTainted && TaintRelatedFun &&
+ (StackDepth < 3 * Opts.InlineMaxStackDepth)) &&
+ (StackDepth >= Opts.InlineMaxStackDepth) &&
(!isSmall(CalleeADC) || IsRecursive))
return false;
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 2af0654e0a..61c348bc93 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -33,7 +33,6 @@
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include <llvm/ADT/DepthFirstIterator.h>
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/ScopeExit.h"
@@ -43,6 +42,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <llvm/ADT/DepthFirstIterator.h>
#include <memory>
#include <queue>
#include <utility>
@@ -245,10 +245,8 @@ public:
ExprEngine::InliningModes
getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
-
- std::set<FunctionDecl*> getDeclsForTaintAnalysis(CallGraph &CG);
- bool isTaintRelatedFunction(const FunctionDecl* FD);
-
+ std::set<FunctionDecl *> getDeclsForTaintAnalysis(CallGraph &CG);
+ bool isTaintRelatedFunction(const FunctionDecl *FD);
/// Build the call graph for all the top level decls of this TU and
/// use it to define the order in which the functions should be visited.
@@ -442,21 +440,27 @@ AnalysisConsumer::getInliningModeForFunction(const Decl *D,
return ExprEngine::Inline_Regular;
}
-bool AnalysisConsumer::isTaintRelatedFunction(const FunctionDecl* FD){
- std::set<std::string> sources = {"scanf","gets","getch","read","fopen","fdopen","freopen","getchar",
- "gets_s","scanf_s","getcwd","readlink","gethostname","getnameinfo","readlinkat","get_current_dir_name",
- "getseuserbyname","getgroups","getlogin","getlogin_r","popen","getenv"};
- std::set<std::string> sinks = {"system", "execv","popen","malloc","calloc","memcpy","strcpy","strncpy"};
+bool AnalysisConsumer::isTaintRelatedFunction(const FunctionDecl *FD) {
+ std::set<std::string> sources = {
+ "scanf", "gets", "getch", "read",
+ "fopen", "fdopen", "freopen", "getchar",
+ "gets_s", "scanf_s", "getcwd", "readlink",
+ "gethostname", "getnameinfo", "readlinkat", "get_current_dir_name",
+ "getseuserbyname", "getgroups", "getlogin", "getlogin_r",
+ "popen", "getenv"};
+ std::set<std::string> sinks = {"system", "execv", "popen", "malloc",
+ "calloc", "memcpy", "strcpy", "strncpy"};
if (!FD || !FD->getCanonicalDecl())
return false;
std::string FN = FD->getCanonicalDecl()->getNameAsString();
- //llvm::errs()<<"Inspecting function if tainted " << FN << "\n";
+ // llvm::errs()<<"Inspecting function if tainted " << FN << "\n";
return (sources.count(FN) || sinks.count(FN));
}
// returns functions declarations required for taint analysis
-std::set<FunctionDecl*> AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG) {
- std::set<FunctionDecl*> TaintedFunctions;
+std::set<FunctionDecl *>
+AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG) {
+ std::set<FunctionDecl *> TaintedFunctions;
for (auto N = llvm::df_begin(&CG), EI = llvm::df_end(&CG); N != EI; N++) {
Decl *D = N->getDecl();
// Skip the abstract root node.
@@ -467,26 +471,31 @@ std::set<FunctionDecl*> AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG
if (!FD)
continue;
if (FD->getDefinition()) {
- llvm::errs() << "Visiting function: " << FD->getNameInfo().getAsString() << "\n";
+ llvm::errs() << "Visiting function: " << FD->getNameInfo().getAsString()
+ << "\n";
}
- for (auto Callee : N->callees()){
+ for (auto Callee : N->callees()) {
FunctionDecl *CFD = dyn_cast<FunctionDecl>(Callee.Callee->getDecl());
if (!CFD)
continue;
if (isTaintRelatedFunction(CFD))
TaintedFunctions.insert(FD);
- if (TaintedFunctions.find(CFD)!=TaintedFunctions.end())//if child is tainted, the parent is also tainted
+ if (TaintedFunctions.find(CFD) !=
+ TaintedFunctions
+ .end()) // if child is tainted, the parent is also tainted
TaintedFunctions.insert(FD);
}
-
- if (isTaintRelatedFunction(FD)){
- llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is tainted\n";
+ if (isTaintRelatedFunction(FD)) {
+ llvm::errs() << "Called Function "
+ << FD->getCanonicalDecl()->getNameAsString()
+ << " is tainted\n";
TaintedFunctions.insert(FD);
} else
- llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is NOT tainted\n";
-
+ llvm::errs() << "Called Function "
+ << FD->getCanonicalDecl()->getNameAsString()
+ << " is NOT tainted\n";
}
return TaintedFunctions;
}
@@ -502,13 +511,13 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
CG.addToCallGraph(LocalTUDecls[i]);
}
- std::set<FunctionDecl*> TaintedFunctions;
- if (Opts.AnalyzerFocusedTaint||Opts.AnalyzerInlineTaintOnly){
+ std::set<FunctionDecl *> TaintedFunctions;
+ if (Opts.AnalyzerFocusedTaint || Opts.AnalyzerInlineTaintOnly) {
TaintedFunctions = getDeclsForTaintAnalysis(CG);
Mgr->setTaintRelatedFunctions(TaintedFunctions);
- llvm::errs()<<"Tainted functions:\n";
- for (FunctionDecl* FD:TaintedFunctions){
- llvm::errs()<<FD->getNameInfo().getAsString() << "\n";
+ llvm::errs() << "Tainted functions:\n";
+ for (FunctionDecl *FD : TaintedFunctions) {
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
}
}
@@ -530,7 +539,6 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
if (!D)
continue;
-
// Skip the functions which have been processed already or previously
// inlined.
if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
diff --git a/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
index d0e1e980d6..8657d8489c 100644
--- a/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
+++ b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
@@ -1,25 +1,21 @@
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
char buf[1024];
-int fetchTaintedString(char *txt){
- scanf("%s", txt);
-}
+int fetchTaintedString(char *txt) { scanf("%s", txt); }
-int exec(char* cmd){
- system(cmd);//warn here
+int exec(char *cmd) {
+ system(cmd); // warn here
}
-void topLevel(){
+void topLevel() {
char cmd[2048] = "/bin/cat ";
char filename[1024];
- fetchTaintedString (filename);
+ fetchTaintedString(filename);
strcat(cmd, filename);
exec(cmd);
}
-void printNum(int data){
- printf("Data:%d\n",data);
-}
\ No newline at end of file
+void printNum(int data) { printf("Data:%d\n", data); }
\ No newline at end of file
|
You can test this locally with the following command:git-clang-format --diff 39babbffc9f44244efaeca8951782a2a6ef814db 470cb4bbdeaa2f5238b28966a8557d7920f21bf1 --extensions cpp,h,c -- clang/lib/StaticAnalyzer/taint_focused/taintcalls.c clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cppView the diff from clang-format here.diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 0b979ecd94..812b48d62a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -293,8 +293,7 @@ public:
ShowConfigOptionsList(false),
ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false),
AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false),
- AnalyzerFocusedTaint(false),
- AnalyzerInlineTaintOnly(false),
+ AnalyzerFocusedTaint(false), AnalyzerInlineTaintOnly(false),
AnalyzerAlwaysInlineTainted(false),
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 27d23714c1..4be764c103 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -42,7 +42,7 @@ class AnalysisManager : public BugReporterData {
ConstraintManagerCreator CreateConstraintMgr;
CheckerManager *CheckerMgr;
- std::set<FunctionDecl*> TaintRelatedFunctions;
+ std::set<FunctionDecl *> TaintRelatedFunctions;
public:
AnalyzerOptions &options;
@@ -60,10 +60,10 @@ public:
AnaCtxMgr.clear();
}
- void setTaintRelatedFunctions(std::set<FunctionDecl*> TaintedFunctions){
+ void setTaintRelatedFunctions(std::set<FunctionDecl *> TaintedFunctions) {
TaintRelatedFunctions = TaintedFunctions;
}
- std::set<FunctionDecl*> getTaintRelatedFunctions(){
+ std::set<FunctionDecl *> getTaintRelatedFunctions() {
return TaintRelatedFunctions;
}
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 85b5796cc1..40ffda0f00 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -81,10 +81,9 @@ static ArgIdxTy fromArgumentCount(unsigned Count) {
/// Handles the resolution of indexes of type ArgIdxTy to Expr*-s.
static const Expr *GetArgExpr(ArgIdxTy ArgIdx, const CallEvent &Call) {
- return ArgIdx == ReturnValueIndex ? Call.getOriginExpr()
- : Call.getArgExpr(ArgIdx);
- };
-
+ return ArgIdx == ReturnValueIndex ? Call.getOriginExpr()
+ : Call.getArgExpr(ArgIdx);
+};
/// Check if the region the expression evaluates to is the standard input,
/// and thus, is tainted.
@@ -865,7 +864,6 @@ void GenericTaintChecker::checkPreCall(const CallEvent &Call,
void GenericTaintChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
-
// Set the marked values as tainted. The return value only accessible from
// checkPostStmt.
ProgramStateRef State = C.getState();
@@ -876,13 +874,12 @@ void GenericTaintChecker::checkPostCall(const CallEvent &Call,
// stored in the state as TaintArgsOnPostVisit set.
TaintArgsOnPostVisitTy TaintArgsMap = State->get<TaintArgsOnPostVisit>();
-
const ArgIdxTy CallNumArgs = fromArgumentCount(Call.getNumArgs());
-
const ImmutableSet<ArgIdxTy> *TaintArgs = TaintArgsMap.lookup(CurrentFrame);
auto &F = State->getStateManager().get_context<ArgIdxFactory>();
- ImmutableSet<ArgIdxTy> ApproxTaintedArgs = F.add(F.getEmptySet(), ReturnValueIndex);
+ ImmutableSet<ArgIdxTy> ApproxTaintedArgs =
+ F.add(F.getEmptySet(), ReturnValueIndex);
if (!C.wasInlined && !TaintArgs) {
llvm::errs() << "PostCall<";
@@ -903,21 +900,22 @@ void GenericTaintChecker::checkPostCall(const CallEvent &Call,
llvm::errs() << "Making return value and writable params tainted.\n";
llvm::errs() << "Number of params:" << CallNumArgs;
- for (ArgIdxTy I = ReturnValueIndex+1; I < CallNumArgs; ++I) {
+ for (ArgIdxTy I = ReturnValueIndex + 1; I < CallNumArgs; ++I) {
const Expr *E = GetArgExpr(I, Call);
if (!E)
continue;
SVal ArgSVal = C.getSVal(E);
- //checking if the argument is a non-const pointer
+ // checking if the argument is a non-const pointer
auto LValue = ArgSVal.getAs<Loc>();
if (!LValue)
continue;
- const QualType ArgTy = LValue->getType(State->getStateManager().getContext());
- if (ArgTy->isPointerType() && !ArgTy.isConstQualified()){
- llvm::errs() << "Param "<< I;
+ const QualType ArgTy =
+ LValue->getType(State->getStateManager().getContext());
+ if (ArgTy->isPointerType() && !ArgTy.isConstQualified()) {
+ llvm::errs() << "Param " << I;
llvm::errs() << "is a non const qualified pointer, so tainting it\n";
ArgTy->dump();
- llvm::errs()<<"\n";
+ llvm::errs() << "\n";
ApproxTaintedArgs = F.add(ApproxTaintedArgs, I);
}
}
@@ -1191,8 +1189,8 @@ void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
Mgr.registerChecker<GenericTaintChecker>();
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
checker->AggressiveTaintPropagation =
- Mgr.getAnalyzerOptions().getCheckerBooleanOption(checker,
- "AggressiveTaintPropagation");
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption(
+ checker, "AggressiveTaintPropagation");
}
bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index ce43548b2c..068c091c3f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -1078,26 +1078,25 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
- bool TaintRelatedFun=false;
+ bool TaintRelatedFun = false;
if (Opts.AnalyzerInlineTaintOnly) {
- std::set<FunctionDecl*> TaintedFunctions = AMgr.getTaintRelatedFunctions();
- // if the function is not taint related skip it.
- auto *FD = dyn_cast<FunctionDecl>(const_cast<Decl*>(D));
- if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
- llvm::errs()
- << "Skipping inlining of not taint related function from the analysis:\n";
- llvm::errs() << FD->getNameInfo().getAsString() << "\n";
- return false;
- } else {
- TaintRelatedFun=true;
- llvm::errs()
- << "tyring to inline taint related function:\n";
- llvm::errs() << FD->getNameInfo().getAsString() << "\n";
- //leave the other budget limits to kick in
- //otherwise the analysis may hang
- //return true;
- }
+ std::set<FunctionDecl *> TaintedFunctions = AMgr.getTaintRelatedFunctions();
+ // if the function is not taint related skip it.
+ auto *FD = dyn_cast<FunctionDecl>(const_cast<Decl *>(D));
+ if (TaintedFunctions.find(FD) == TaintedFunctions.end()) {
+ llvm::errs() << "Skipping inlining of not taint related function from "
+ "the analysis:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ return false;
+ } else {
+ TaintRelatedFun = true;
+ llvm::errs() << "tyring to inline taint related function:\n";
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
+ // leave the other budget limits to kick in
+ // otherwise the analysis may hang
+ // return true;
+ }
}
// The auto-synthesized bodies are essential to inline as they are
// usually small and commonly used. Note: we should do this check early on to
@@ -1143,8 +1142,9 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
bool IsRecursive = false;
unsigned StackDepth = 0;
examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
- if (!(Opts.AnalyzerAlwaysInlineTainted && TaintRelatedFun && (StackDepth < 3*Opts.InlineMaxStackDepth))
- && (StackDepth >= Opts.InlineMaxStackDepth) &&
+ if (!(Opts.AnalyzerAlwaysInlineTainted && TaintRelatedFun &&
+ (StackDepth < 3 * Opts.InlineMaxStackDepth)) &&
+ (StackDepth >= Opts.InlineMaxStackDepth) &&
(!isSmall(CalleeADC) || IsRecursive))
return false;
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 2af0654e0a..61c348bc93 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -33,7 +33,6 @@
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include <llvm/ADT/DepthFirstIterator.h>
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/ScopeExit.h"
@@ -43,6 +42,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <llvm/ADT/DepthFirstIterator.h>
#include <memory>
#include <queue>
#include <utility>
@@ -245,10 +245,8 @@ public:
ExprEngine::InliningModes
getInliningModeForFunction(const Decl *D, const SetOfConstDecls &Visited);
-
- std::set<FunctionDecl*> getDeclsForTaintAnalysis(CallGraph &CG);
- bool isTaintRelatedFunction(const FunctionDecl* FD);
-
+ std::set<FunctionDecl *> getDeclsForTaintAnalysis(CallGraph &CG);
+ bool isTaintRelatedFunction(const FunctionDecl *FD);
/// Build the call graph for all the top level decls of this TU and
/// use it to define the order in which the functions should be visited.
@@ -442,21 +440,27 @@ AnalysisConsumer::getInliningModeForFunction(const Decl *D,
return ExprEngine::Inline_Regular;
}
-bool AnalysisConsumer::isTaintRelatedFunction(const FunctionDecl* FD){
- std::set<std::string> sources = {"scanf","gets","getch","read","fopen","fdopen","freopen","getchar",
- "gets_s","scanf_s","getcwd","readlink","gethostname","getnameinfo","readlinkat","get_current_dir_name",
- "getseuserbyname","getgroups","getlogin","getlogin_r","popen","getenv"};
- std::set<std::string> sinks = {"system", "execv","popen","malloc","calloc","memcpy","strcpy","strncpy"};
+bool AnalysisConsumer::isTaintRelatedFunction(const FunctionDecl *FD) {
+ std::set<std::string> sources = {
+ "scanf", "gets", "getch", "read",
+ "fopen", "fdopen", "freopen", "getchar",
+ "gets_s", "scanf_s", "getcwd", "readlink",
+ "gethostname", "getnameinfo", "readlinkat", "get_current_dir_name",
+ "getseuserbyname", "getgroups", "getlogin", "getlogin_r",
+ "popen", "getenv"};
+ std::set<std::string> sinks = {"system", "execv", "popen", "malloc",
+ "calloc", "memcpy", "strcpy", "strncpy"};
if (!FD || !FD->getCanonicalDecl())
return false;
std::string FN = FD->getCanonicalDecl()->getNameAsString();
- //llvm::errs()<<"Inspecting function if tainted " << FN << "\n";
+ // llvm::errs()<<"Inspecting function if tainted " << FN << "\n";
return (sources.count(FN) || sinks.count(FN));
}
// returns functions declarations required for taint analysis
-std::set<FunctionDecl*> AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG) {
- std::set<FunctionDecl*> TaintedFunctions;
+std::set<FunctionDecl *>
+AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG) {
+ std::set<FunctionDecl *> TaintedFunctions;
for (auto N = llvm::df_begin(&CG), EI = llvm::df_end(&CG); N != EI; N++) {
Decl *D = N->getDecl();
// Skip the abstract root node.
@@ -467,26 +471,31 @@ std::set<FunctionDecl*> AnalysisConsumer::getDeclsForTaintAnalysis(CallGraph &CG
if (!FD)
continue;
if (FD->getDefinition()) {
- llvm::errs() << "Visiting function: " << FD->getNameInfo().getAsString() << "\n";
+ llvm::errs() << "Visiting function: " << FD->getNameInfo().getAsString()
+ << "\n";
}
- for (auto Callee : N->callees()){
+ for (auto Callee : N->callees()) {
FunctionDecl *CFD = dyn_cast<FunctionDecl>(Callee.Callee->getDecl());
if (!CFD)
continue;
if (isTaintRelatedFunction(CFD))
TaintedFunctions.insert(FD);
- if (TaintedFunctions.find(CFD)!=TaintedFunctions.end())//if child is tainted, the parent is also tainted
+ if (TaintedFunctions.find(CFD) !=
+ TaintedFunctions
+ .end()) // if child is tainted, the parent is also tainted
TaintedFunctions.insert(FD);
}
-
- if (isTaintRelatedFunction(FD)){
- llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is tainted\n";
+ if (isTaintRelatedFunction(FD)) {
+ llvm::errs() << "Called Function "
+ << FD->getCanonicalDecl()->getNameAsString()
+ << " is tainted\n";
TaintedFunctions.insert(FD);
} else
- llvm::errs()<<"Called Function "<<FD->getCanonicalDecl()->getNameAsString()<<" is NOT tainted\n";
-
+ llvm::errs() << "Called Function "
+ << FD->getCanonicalDecl()->getNameAsString()
+ << " is NOT tainted\n";
}
return TaintedFunctions;
}
@@ -502,13 +511,13 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
CG.addToCallGraph(LocalTUDecls[i]);
}
- std::set<FunctionDecl*> TaintedFunctions;
- if (Opts.AnalyzerFocusedTaint||Opts.AnalyzerInlineTaintOnly){
+ std::set<FunctionDecl *> TaintedFunctions;
+ if (Opts.AnalyzerFocusedTaint || Opts.AnalyzerInlineTaintOnly) {
TaintedFunctions = getDeclsForTaintAnalysis(CG);
Mgr->setTaintRelatedFunctions(TaintedFunctions);
- llvm::errs()<<"Tainted functions:\n";
- for (FunctionDecl* FD:TaintedFunctions){
- llvm::errs()<<FD->getNameInfo().getAsString() << "\n";
+ llvm::errs() << "Tainted functions:\n";
+ for (FunctionDecl *FD : TaintedFunctions) {
+ llvm::errs() << FD->getNameInfo().getAsString() << "\n";
}
}
@@ -530,7 +539,6 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
if (!D)
continue;
-
// Skip the functions which have been processed already or previously
// inlined.
if (shouldSkipFunction(D, Visited, VisitedAsTopLevel))
diff --git a/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
index d0e1e980d6..8657d8489c 100644
--- a/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
+++ b/clang/lib/StaticAnalyzer/taint_focused/taintcalls.c
@@ -1,25 +1,21 @@
-#include <stdlib.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
char buf[1024];
-int fetchTaintedString(char *txt){
- scanf("%s", txt);
-}
+int fetchTaintedString(char *txt) { scanf("%s", txt); }
-int exec(char* cmd){
- system(cmd);//warn here
+int exec(char *cmd) {
+ system(cmd); // warn here
}
-void topLevel(){
+void topLevel() {
char cmd[2048] = "/bin/cat ";
char filename[1024];
- fetchTaintedString (filename);
+ fetchTaintedString(filename);
strcat(cmd, filename);
exec(cmd);
}
-void printNum(int data){
- printf("Data:%d\n",data);
-}
\ No newline at end of file
+void printNum(int data) { printf("Data:%d\n", data); }
\ No newline at end of file
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.