diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index d442b26b395..2ceb6313920 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -98,13 +98,20 @@ private: } /// Catch taint related bugs. Check if tainted data is passed to a - /// system call etc. - bool checkPre(const CallExpr *CE, CheckerContext &C) const; + /// system call etc. Returns true on matching. + bool checkPre(const CallExpr *CE, const FunctionDecl *FDecl, StringRef Name, + CheckerContext &C) const; - /// Add taint sources on a pre-visit. - void addSourcesPre(const CallExpr *CE, CheckerContext &C) const; + /// Add taint sources on a pre-visit. Returns true on matching. + bool addSourcesPre(const CallExpr *CE, const FunctionDecl *FDecl, + StringRef Name, CheckerContext &C) const; - /// Propagate taint generated at pre-visit. + /// Mark filter's arguments not tainted on a pre-visit. Returns true on + /// matching. + bool addFiltersPre(const CallExpr *CE, StringRef Name, + CheckerContext &C) const; + + /// Propagate taint generated at pre-visit. Returns true on matching. bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const; /// Check if the region the expression evaluates to is the standard input, @@ -442,14 +449,26 @@ GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule( void GenericTaintChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { + const FunctionDecl *FDecl = C.getCalleeDecl(CE); + // Check for non-global functions. + if (!FDecl || FDecl->getKind() != Decl::Function) + return; + + StringRef Name = C.getCalleeName(FDecl); + if (Name.empty()) + return; + // Check for taintedness related errors first: system call, uncontrolled // format string, tainted buffer size. - if (checkPre(CE, C)) + if (checkPre(CE, FDecl, Name, C)) return; // Marks the function's arguments and/or return value tainted if it present in // the list. - addSourcesPre(CE, C); + if (addSourcesPre(CE, FDecl, Name, C)) + return; + + addFiltersPre(CE, Name, C); } void GenericTaintChecker::checkPostStmt(const CallExpr *CE, @@ -464,31 +483,46 @@ void GenericTaintChecker::printState(raw_ostream &Out, ProgramStateRef State, printTaint(State, Out, NL, Sep); } -void GenericTaintChecker::addSourcesPre(const CallExpr *CE, +bool GenericTaintChecker::addSourcesPre(const CallExpr *CE, + const FunctionDecl *FDecl, + StringRef Name, CheckerContext &C) const { - ProgramStateRef State = nullptr; - const FunctionDecl *FDecl = C.getCalleeDecl(CE); - if (!FDecl || FDecl->getKind() != Decl::Function) - return; - - StringRef Name = C.getCalleeName(FDecl); - if (Name.empty()) - return; - // First, try generating a propagation rule for this function. TaintPropagationRule Rule = TaintPropagationRule::getTaintPropagationRule( this->CustomPropagations, FDecl, Name, C); if (!Rule.isNull()) { - State = Rule.process(CE, C); - if (!State) - return; - C.addTransition(State); - return; + ProgramStateRef State = Rule.process(CE, C); + if (State) { + C.addTransition(State); + return true; + } } + return false; +} - if (!State) - return; - C.addTransition(State); +bool GenericTaintChecker::addFiltersPre(const CallExpr *CE, StringRef Name, + CheckerContext &C) const { + auto It = CustomFilters.find(Name); + if (It == CustomFilters.end()) + return false; + + ProgramStateRef State = C.getState(); + const ArgVector &Args = It->getValue(); + for (unsigned ArgNum : Args) { + if (ArgNum >= CE->getNumArgs()) + continue; + + const Expr *Arg = CE->getArg(ArgNum); + Optional<SVal> V = getPointedToSVal(C, Arg); + if (V) + State = removeTaint(State, *V); + } + + if (State != C.getState()) { + C.addTransition(State); + return true; + } + return false; } bool GenericTaintChecker::propagateFromPre(const CallExpr *CE, @@ -530,19 +564,12 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE, } bool GenericTaintChecker::checkPre(const CallExpr *CE, + const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) const { if (checkUncontrolledFormatString(CE, C)) return true; - const FunctionDecl *FDecl = C.getCalleeDecl(CE); - if (!FDecl || FDecl->getKind() != Decl::Function) - return false; - - StringRef Name = C.getCalleeName(FDecl); - if (Name.empty()) - return false; - if (checkSystemCall(CE, Name, C)) return true; |