1 //== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This checker defines the attack surface for generic taint propagation. 11 // 12 // The taint information produced by it might be useful to other checkers. For 13 // example, checkers should report errors which involve tainted data more 14 // aggressively, even if the involved symbols are under constrained. 15 // 16 //===----------------------------------------------------------------------===// 17 #include "ClangSACheckers.h" 18 #include "clang/StaticAnalyzer/Core/Checker.h" 19 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 22 23 using namespace clang; 24 using namespace ento; 25 26 namespace { 27 class GenericTaintChecker : public Checker< check::PostStmt<CallExpr> > { 28 29 mutable llvm::OwningPtr<BuiltinBug> BT; 30 31 /// Functions defining the attacke surface. 32 typedef void (GenericTaintChecker::*FnCheck)(const CallExpr *, 33 CheckerContext &C) const; 34 void processScanf(const CallExpr *CE, CheckerContext &C) const; 35 void processRetTaint(const CallExpr *CE, CheckerContext &C) const; 36 37 public: 38 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; 39 }; 40 } 41 42 void GenericTaintChecker::checkPostStmt(const CallExpr *CE, 43 CheckerContext &C) const { 44 if (!C.getState()) 45 return; 46 47 StringRef Name = C.getCalleeName(CE); 48 49 // Define the attack surface. 50 // Set the evaluation function by switching on the callee name. 51 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 52 .Case("scanf", &GenericTaintChecker::processScanf) 53 .Case("getchar", &GenericTaintChecker::processRetTaint) 54 .Default(NULL); 55 56 // If the callee isn't defined, it is not of security concern. 57 // Check and evaluate the call. 58 if (evalFunction) 59 (this->*evalFunction)(CE, C); 60 61 } 62 static SymbolRef getPointedToSymbol(const ProgramState *State, 63 const Expr* Arg) { 64 SVal AddrVal = State->getSVal(Arg->IgnoreParenCasts()); 65 Loc *AddrLoc = dyn_cast<Loc>(&AddrVal); 66 SVal Val = State->getSVal(*AddrLoc); 67 return Val.getAsSymbol(); 68 } 69 70 71 void GenericTaintChecker::processScanf(const CallExpr *CE, 72 CheckerContext &C) const { 73 const ProgramState *State = C.getState(); 74 assert(CE->getNumArgs() == 2); 75 SVal x = State->getSVal(CE->getArg(1)); 76 // All arguments except for the very first one should get taint. 77 for (unsigned int i = 1; i < CE->getNumArgs(); ++i) { 78 // The arguments are pointer arguments. The data they are pointing at is 79 // tainted after the call. 80 const Expr* Arg = CE->getArg(i); 81 SymbolRef Sym = getPointedToSymbol(State, Arg); 82 if (Sym) 83 State = State->addTaint(Sym); 84 } 85 C.addTransition(State); 86 87 } 88 89 void GenericTaintChecker::processRetTaint(const CallExpr *CE, 90 CheckerContext &C) const { 91 const ProgramState *NewState = C.getState()->addTaint(CE); 92 C.addTransition(NewState); 93 } 94 95 void ento::registerGenericTaintChecker(CheckerManager &mgr) { 96 mgr.registerChecker<GenericTaintChecker>(); 97 } 98