1df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks//== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=// 2df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 3df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// The LLVM Compiler Infrastructure 4df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 5df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// This file is distributed under the University of Illinois Open Source 6df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// License. See LICENSE.TXT for details. 7df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 8df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks//===----------------------------------------------------------------------===// 9df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 10df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// This checker defines the attack surface for generic taint propagation. 11df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 12df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// The taint information produced by it might be useful to other checkers. For 13df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// example, checkers should report errors which involve tainted data more 14df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// aggressively, even if the involved symbols are under constrained. 15df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks// 16df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks//===----------------------------------------------------------------------===// 17df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks#include "ClangSACheckers.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/Attr.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/Builtins.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks#include "clang/StaticAnalyzer/Core/Checker.h" 22df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks#include "clang/StaticAnalyzer/Core/CheckerManager.h" 23df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 249ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 251fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks#include <climits> 26df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 27df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaksusing namespace clang; 28df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaksusing namespace ento; 29df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 30df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaksnamespace { 31efd6989f4644c8460854606e085fc69535054058Anna Zaksclass GenericTaintChecker : public Checker< check::PostStmt<CallExpr>, 329ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks check::PreStmt<CallExpr> > { 339ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zakspublic: 348568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks static void *getTag() { static int Tag; return &Tag; } 358568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 368568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; 378568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 388568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; 39df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 409ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaksprivate: 41b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks static const unsigned InvalidArgIndex = UINT_MAX; 42b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks /// Denotes the return vale. 43b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks static const unsigned ReturnValueIndex = UINT_MAX - 1; 448568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BugType> BT; 469b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks inline void initBugType() const { 479b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (!BT) 48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data")); 499b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 508f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks 511fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// \brief Catch taint related bugs. Check if tainted data is passed to a 521fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// system call etc. 539f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks bool checkPre(const CallExpr *CE, CheckerContext &C) const; 549f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 551fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// \brief Add taint sources on a pre-visit. 561fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks void addSourcesPre(const CallExpr *CE, CheckerContext &C) const; 571fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 581fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// \brief Propagate taint generated at pre-visit. 591fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const; 601fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 611fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// \brief Add taint sources on a post visit. 621fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks void addSourcesPost(const CallExpr *CE, CheckerContext &C) const; 631fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 64b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks /// Check if the region the expression evaluates to is the standard input, 65b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks /// and thus, is tainted. 66b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks static bool isStdin(const Expr *E, CheckerContext &C); 67b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks 681fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks /// \brief Given a pointer argument, get the symbol of the value it contains 698f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks /// (points to). 707cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks static SymbolRef getPointedToSymbol(CheckerContext &C, const Expr *Arg); 71df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 729ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks /// Functions defining the attack surface. 738bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *, 749ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks CheckerContext &C) const; 758bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const; 768bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const; 778bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const; 789ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 799ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks /// Taint the scanned input if the file is tainted. 808bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const; 81df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 829f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks /// Check for CWE-134: Uncontrolled Format String. 838568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks static const char MsgUncontrolledFormatString[]; 849f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks bool checkUncontrolledFormatString(const CallExpr *CE, 859f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks CheckerContext &C) const; 869f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 878568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks /// Check for: 888568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks /// CERT/STR02-C. "Sanitize data passed to complex subsystems" 898568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks /// CWE-78, "Failure to Sanitize Data into an OS Command" 908568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks static const char MsgSanitizeSystemArgs[]; 918568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks bool checkSystemCall(const CallExpr *CE, StringRef Name, 928568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks CheckerContext &C) const; 939ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 944e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks /// Check if tainted data is used as a buffer size ins strn.. functions, 954e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks /// and allocators. 964e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks static const char MsgTaintedBufferSize[]; 974e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl, 984e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks CheckerContext &C) const; 994e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 1008568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks /// Generate a report if the expression is tainted or points to tainted data. 1018568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks bool generateReportIfTainted(const Expr *E, const char Msg[], 1028568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks CheckerContext &C) const; 103022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 104022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 105cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko typedef SmallVector<unsigned, 2> ArgVector; 106022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 107022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// \brief A struct used to specify taint propagation rules for a function. 108022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// 109022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// If any of the possible taint source arguments is tainted, all of the 110022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// destination arguments should also be tainted. Use InvalidArgIndex in the 111022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// src list to specify that all of the arguments can introduce taint. Use 112022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// InvalidArgIndex in the dst arguments to signify that all the non-const 113022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// pointer and reference arguments might be tainted on return. If 114022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// ReturnValueIndex is added to the dst list, the return value will be 115022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// tainted. 116022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks struct TaintPropagationRule { 117022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// List of arguments which can be taint sources and should be checked. 118022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks ArgVector SrcArgs; 119022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks /// List of arguments which should be tainted on function return. 120022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks ArgVector DstArgs; 1219b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // TODO: Check if using other data structures would be more optimal. 122022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 123022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks TaintPropagationRule() {} 124022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 1259b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks TaintPropagationRule(unsigned SArg, 1269b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks unsigned DArg, bool TaintRet = false) { 127022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks SrcArgs.push_back(SArg); 128022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks DstArgs.push_back(DArg); 1299b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (TaintRet) 1309b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks DstArgs.push_back(ReturnValueIndex); 1319b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 1329b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 1339b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks TaintPropagationRule(unsigned SArg1, unsigned SArg2, 1349b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks unsigned DArg, bool TaintRet = false) { 1359b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks SrcArgs.push_back(SArg1); 1369b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks SrcArgs.push_back(SArg2); 1379b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks DstArgs.push_back(DArg); 1389b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (TaintRet) 1399b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks DstArgs.push_back(ReturnValueIndex); 140022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 1419ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 1429b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks /// Get the propagation rule for a given function. 1439b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks static TaintPropagationRule 1449b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks getTaintPropagationRule(const FunctionDecl *FDecl, 1459b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks StringRef Name, 1469b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks CheckerContext &C); 1479b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 148022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); } 149022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks inline void addDstArg(unsigned A) { DstArgs.push_back(A); } 150022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 1519b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks inline bool isNull() const { return SrcArgs.empty(); } 1529b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 1539b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks inline bool isDestinationArgument(unsigned ArgNum) const { 1549b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return (std::find(DstArgs.begin(), 1559b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks DstArgs.end(), ArgNum) != DstArgs.end()); 1569b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 157022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 158b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks static inline bool isTaintedOrPointsToTainted(const Expr *E, 1598bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State, 160b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks CheckerContext &C) { 161b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks return (State->isTainted(E, C.getLocationContext()) || isStdin(E, C) || 162b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks (E->getType().getTypePtr()->isPointerType() && 163b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks State->isTainted(getPointedToSymbol(C, E)))); 164b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks } 165b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks 1667cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks /// \brief Pre-process a function which propagates taint according to the 1677cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks /// taint rule. 1688bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const; 1697cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks 1707cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks }; 171df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks}; 1729b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 1739b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaksconst unsigned GenericTaintChecker::ReturnValueIndex; 1749b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaksconst unsigned GenericTaintChecker::InvalidArgIndex; 1759b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 1768568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaksconst char GenericTaintChecker::MsgUncontrolledFormatString[] = 1775fdadf4b643dd2f7a467244946dc1587b2f9ed1fAnna Zaks "Untrusted data is used as a format string " 1785fdadf4b643dd2f7a467244946dc1587b2f9ed1fAnna Zaks "(CWE-134: Uncontrolled Format String)"; 1798568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 1808568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaksconst char GenericTaintChecker::MsgSanitizeSystemArgs[] = 1815fdadf4b643dd2f7a467244946dc1587b2f9ed1fAnna Zaks "Untrusted data is passed to a system call " 1828568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks "(CERT/STR02-C. Sanitize data passed to complex subsystems)"; 1834e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 1844e46221e38b7d434fbecb1cd56b259437206d246Anna Zaksconst char GenericTaintChecker::MsgTaintedBufferSize[] = 1855fdadf4b643dd2f7a467244946dc1587b2f9ed1fAnna Zaks "Untrusted data is used to specify the buffer size " 1864e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for " 1874e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks "character data and the null terminator)"; 1884e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 1894e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks} // end of anonymous namespace 190df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 1911fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks/// A set which is used to pass information from call pre-visit instruction 1921fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks/// to the call post-visit. The values are unsigned integers, which are either 1931fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks/// ReturnValueIndex, or indexes of the pointer/reference argument, which 1941fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks/// points to data, which should be tainted on return. 195166d502d5367ceacd1313a33cac43b1048b8524dJordan RoseREGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned) 1969ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 1979b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna ZaksGenericTaintChecker::TaintPropagationRule 1989b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna ZaksGenericTaintChecker::TaintPropagationRule::getTaintPropagationRule( 1999b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks const FunctionDecl *FDecl, 2009b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks StringRef Name, 2019b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks CheckerContext &C) { 202b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks // TODO: Currently, we might loose precision here: we always mark a return 203b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks // value as tainted even if it's just a pointer, pointing to tainted data. 204b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks 2059b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Check for exact name match for functions without builtin substitutes. 2069b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks TaintPropagationRule Rule = llvm::StringSwitch<TaintPropagationRule>(Name) 2079b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks .Case("atoi", TaintPropagationRule(0, ReturnValueIndex)) 2089b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks .Case("atol", TaintPropagationRule(0, ReturnValueIndex)) 2099b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks .Case("atoll", TaintPropagationRule(0, ReturnValueIndex)) 210b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getc", TaintPropagationRule(0, ReturnValueIndex)) 211b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex)) 212b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex)) 213b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getw", TaintPropagationRule(0, ReturnValueIndex)) 214b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("toupper", TaintPropagationRule(0, ReturnValueIndex)) 215b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("tolower", TaintPropagationRule(0, ReturnValueIndex)) 216b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("strchr", TaintPropagationRule(0, ReturnValueIndex)) 217b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex)) 2182bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("read", TaintPropagationRule(0, 2, 1, true)) 2192bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true)) 220b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true)) 221b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("fgets", TaintPropagationRule(2, 0, true)) 222b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getline", TaintPropagationRule(2, 0)) 223b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getdelim", TaintPropagationRule(3, 0)) 224b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex)) 2259b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks .Default(TaintPropagationRule()); 2269b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2279b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (!Rule.isNull()) 2289b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return Rule; 2299b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2309b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Check if it's one of the memory setting/copying functions. 2319b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // This check is specialized but faster then calling isCLibraryFunction. 2329b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks unsigned BId = 0; 2339b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if ( (BId = FDecl->getMemoryFunctionKind()) ) 2349b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks switch(BId) { 2359b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BImemcpy: 2369b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BImemmove: 2379b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BIstrncpy: 2389b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BIstrncat: 2399b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(1, 2, 0, true); 2409b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BIstrlcpy: 2419b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BIstrlcat: 2429b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(1, 2, 0, false); 2439b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks case Builtin::BIstrndup: 2449b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(0, 1, ReturnValueIndex); 2459b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2469b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks default: 2479b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks break; 2489b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks }; 2499b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2509b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Process all other functions which could be defined as builtins. 2519b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (Rule.isNull()) { 2529b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks if (C.isCLibraryFunction(FDecl, "snprintf") || 2539b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks C.isCLibraryFunction(FDecl, "sprintf")) 2549b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(InvalidArgIndex, 0, true); 2559b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks else if (C.isCLibraryFunction(FDecl, "strcpy") || 2569b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks C.isCLibraryFunction(FDecl, "stpcpy") || 2579b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks C.isCLibraryFunction(FDecl, "strcat")) 2589b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(1, 0, true); 2599b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks else if (C.isCLibraryFunction(FDecl, "bcopy")) 2609b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(0, 2, 1, false); 2619b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks else if (C.isCLibraryFunction(FDecl, "strdup") || 2629b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks C.isCLibraryFunction(FDecl, "strdupa")) 2639b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(0, ReturnValueIndex); 2644e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks else if (C.isCLibraryFunction(FDecl, "wcsdup")) 2654e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks return TaintPropagationRule(0, ReturnValueIndex); 2669b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 2679b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2689b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Skipping the following functions, since they might be used for cleansing 2699b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // or smart memory copy: 27048d798ce32447607144db70a484cdb99c1180663Benjamin Kramer // - memccpy - copying until hitting a special character. 2719b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2729b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return TaintPropagationRule(); 2738f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks} 2748f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks 2759ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaksvoid GenericTaintChecker::checkPreStmt(const CallExpr *CE, 2769ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks CheckerContext &C) const { 2779f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Check for errors first. 2789f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks if (checkPre(CE, C)) 2799f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return; 280df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 2819f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Add taint second. 2821fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks addSourcesPre(CE, C); 2839f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks} 2849f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 2859f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaksvoid GenericTaintChecker::checkPostStmt(const CallExpr *CE, 2869f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks CheckerContext &C) const { 2871fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (propagateFromPre(CE, C)) 2881fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return; 2891fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks addSourcesPost(CE, C); 2909f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks} 2919f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 2921fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaksvoid GenericTaintChecker::addSourcesPre(const CallExpr *CE, 2931fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks CheckerContext &C) const { 2946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ProgramStateRef State = nullptr; 2959b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks const FunctionDecl *FDecl = C.getCalleeDecl(CE); 2965ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose if (!FDecl || FDecl->getKind() != Decl::Function) 2975ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose return; 2985ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose 2999b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks StringRef Name = C.getCalleeName(FDecl); 3001fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (Name.empty()) 3011fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return; 302022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 3039b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // First, try generating a propagation rule for this function. 3049b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks TaintPropagationRule Rule = 3059b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C); 306022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (!Rule.isNull()) { 3077cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks State = Rule.process(CE, C); 308022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (!State) 309022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks return; 310022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks C.addTransition(State); 3119b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return; 312022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 313022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 3149b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Otherwise, check if we have custom pre-processing implemented. 3159ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 3161fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks .Case("fscanf", &GenericTaintChecker::preFscanf) 3176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines .Default(nullptr); 3189ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks // Check and evaluate the call. 3199ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks if (evalFunction) 3209ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks State = (this->*evalFunction)(CE, C); 3219ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks if (!State) 3229ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks return; 3239ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks C.addTransition(State); 3249b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 3259ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks} 3269ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 3271fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaksbool GenericTaintChecker::propagateFromPre(const CallExpr *CE, 3281fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks CheckerContext &C) const { 3298bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 3301fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3311fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // Depending on what was tainted at pre-visit, we determined a set of 3321fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // arguments which should be tainted after the function returns. These are 3331fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // stored in the state as TaintArgsOnPostVisit set. 334166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose TaintArgsOnPostVisitTy TaintArgs = State->get<TaintArgsOnPostVisit>(); 335b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks if (TaintArgs.isEmpty()) 336b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks return false; 337b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks 3381fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks for (llvm::ImmutableSet<unsigned>::iterator 3391fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) { 3401fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks unsigned ArgNum = *I; 3411fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3421fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // Special handling for the tainted return value. 3431fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (ArgNum == ReturnValueIndex) { 3441fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks State = State->addTaint(CE, C.getLocationContext()); 3451fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks continue; 3461fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks } 3471fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3481fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // The arguments are pointer arguments. The data they are pointing at is 3491fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // tainted after the call. 350259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < (ArgNum + 1)) 351259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return false; 3521fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks const Expr* Arg = CE->getArg(ArgNum); 3537cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks SymbolRef Sym = getPointedToSymbol(C, Arg); 3541fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (Sym) 3551fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks State = State->addTaint(Sym); 3561fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks } 3571fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3581fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // Clear up the taint info from the state. 3591fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks State = State->remove<TaintArgsOnPostVisit>(); 3601fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3611fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (State != C.getState()) { 3621fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks C.addTransition(State); 3631fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return true; 3641fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks } 3651fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return false; 3661fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks} 3671fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 3681fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaksvoid GenericTaintChecker::addSourcesPost(const CallExpr *CE, 3691fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks CheckerContext &C) const { 370df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // Define the attack surface. 371df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // Set the evaluation function by switching on the callee name. 3725ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose const FunctionDecl *FDecl = C.getCalleeDecl(CE); 3735ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose if (!FDecl || FDecl->getKind() != Decl::Function) 3745ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose return; 3755ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose 3765ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose StringRef Name = C.getCalleeName(FDecl); 3771fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks if (Name.empty()) 3781fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return; 379df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 3809ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("scanf", &GenericTaintChecker::postScanf) 3811009ac715501a4fa1951d94722dcbe6ab30068f8Anna Zaks // TODO: Add support for vfscanf & family. 3829ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("getchar", &GenericTaintChecker::postRetTaint) 383b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint) 3849ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("getenv", &GenericTaintChecker::postRetTaint) 3859ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("fopen", &GenericTaintChecker::postRetTaint) 3869ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("fdopen", &GenericTaintChecker::postRetTaint) 3879ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks .Case("freopen", &GenericTaintChecker::postRetTaint) 388b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("getch", &GenericTaintChecker::postRetTaint) 389b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("wgetch", &GenericTaintChecker::postRetTaint) 3902bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("socket", &GenericTaintChecker::postSocket) 3916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines .Default(nullptr); 392df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 393df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // If the callee isn't defined, it is not of security concern. 394df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // Check and evaluate the call. 3956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ProgramStateRef State = nullptr; 396df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks if (evalFunction) 3979ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks State = (this->*evalFunction)(CE, C); 3989ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks if (!State) 3999ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks return; 400df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 4019ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks C.addTransition(State); 402df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks} 4038f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks 4049f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaksbool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{ 4059f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 4069f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks if (checkUncontrolledFormatString(CE, C)) 4079f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return true; 4089f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 4094e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks const FunctionDecl *FDecl = C.getCalleeDecl(CE); 4105ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose if (!FDecl || FDecl->getKind() != Decl::Function) 4115ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose return false; 4125ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose 4134e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks StringRef Name = C.getCalleeName(FDecl); 4148568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (Name.empty()) 4158568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return false; 4168568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 4178568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (checkSystemCall(CE, Name, C)) 4188568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return true; 4198568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 4204e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks if (checkTaintedBufferSize(CE, FDecl, C)) 4214e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks return true; 4224e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 4239f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return false; 4249f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks} 4259f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 4268f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna ZaksSymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C, 4277cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks const Expr* Arg) { 4288bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 4295eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext()); 430d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (AddrVal.isUnknownOrUndef()) 4316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 432e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks 433dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<Loc> AddrLoc = AddrVal.getAs<Loc>(); 4347cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks if (!AddrLoc) 4356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4368f4caf5fec2de9b18f9c5fc69696d9f6cf66bcc5Anna Zaks 43771d29095d27e94b00083259c06a45f5294501697Anna Zaks const PointerType *ArgTy = 43871d29095d27e94b00083259c06a45f5294501697Anna Zaks dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr()); 439665b00265858a47f3ccd80b2f27b250c54f5fd5dAnna Zaks SVal Val = State->getSVal(*AddrLoc, 440665b00265858a47f3ccd80b2f27b250c54f5fd5dAnna Zaks ArgTy ? ArgTy->getPointeeType(): QualType()); 441df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks return Val.getAsSymbol(); 442df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks} 443df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 4448bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef 4457cdfe298ae49e381f6d78fc93855c372e5173dd0Anna ZaksGenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE, 4467cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks CheckerContext &C) const { 4478bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 448022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 449022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Check for taint in arguments. 450022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks bool IsTainted = false; 4517cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks for (ArgVector::const_iterator I = SrcArgs.begin(), 4527cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks E = SrcArgs.end(); I != E; ++I) { 453022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks unsigned ArgNum = *I; 454022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 455022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (ArgNum == InvalidArgIndex) { 4569b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // Check if any of the arguments is tainted, but skip the 4579b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks // destination arguments. 4589b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks for (unsigned int i = 0; i < CE->getNumArgs(); ++i) { 4597cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks if (isDestinationArgument(i)) 4609b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks continue; 461b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C))) 462022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks break; 4639b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 464022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks break; 465022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 466022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 467259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < (ArgNum + 1)) 468259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return State; 469b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C))) 470022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks break; 471022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 472022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (!IsTainted) 473022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks return State; 474022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 475022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Mark the arguments which should be tainted after the function returns. 4767cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks for (ArgVector::const_iterator I = DstArgs.begin(), 4777cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks E = DstArgs.end(); I != E; ++I) { 478022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks unsigned ArgNum = *I; 479022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 480022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Should we mark all arguments as tainted? 481022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (ArgNum == InvalidArgIndex) { 482022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // For all pointer and references that were passed in: 483022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // If they are not pointing to const data, mark data as tainted. 484022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // TODO: So far we are just going one level down; ideally we'd need to 485022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // recurse here. 486022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks for (unsigned int i = 0; i < CE->getNumArgs(); ++i) { 487022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks const Expr *Arg = CE->getArg(i); 488022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Process pointer argument. 489022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks const Type *ArgTy = Arg->getType().getTypePtr(); 490022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks QualType PType = ArgTy->getPointeeType(); 491022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if ((!PType.isNull() && !PType.isConstQualified()) 492022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks || (ArgTy->isReferenceType() && !Arg->getType().isConstQualified())) 493022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks State = State->add<TaintArgsOnPostVisit>(i); 494022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 495022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks continue; 496022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 497022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 498022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Should mark the return value? 499022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks if (ArgNum == ReturnValueIndex) { 500022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex); 501022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks continue; 502022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 503022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 504022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks // Mark the given argument. 505022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks assert(ArgNum < CE->getNumArgs()); 506022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks State = State->add<TaintArgsOnPostVisit>(ArgNum); 507022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks } 508022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 509022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks return State; 510022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks} 511022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 512022b3f4490bbdcde7b3f18ce0498f9a73b6cbf53Anna Zaks 5131fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks// If argument 0 (file descriptor) is tainted, all arguments except for arg 0 5141fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks// and arg 1 should get taint. 5158bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE, 5169ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks CheckerContext &C) const { 5179ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks assert(CE->getNumArgs() >= 2); 5188bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 5199ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 5209ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks // Check is the file descriptor is tainted. 5215eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (State->isTainted(CE->getArg(0), C.getLocationContext()) || 5221fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks isStdin(CE->getArg(0), C)) { 5231fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks // All arguments except for the first two should get taint. 5241fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks for (unsigned int i = 2; i < CE->getNumArgs(); ++i) 5251fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks State = State->add<TaintArgsOnPostVisit>(i); 5261fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks return State; 5271fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks } 5281fb826a6fd893234f32b0b91bb92ea4d127788adAnna Zaks 5296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 5309ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks} 5319ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks 5322bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks 5332bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks// If argument 0(protocol domain) is network, the return value should get taint. 5348bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE, 535259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks CheckerContext &C) const { 5368bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 537259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 538259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return State; 5392bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks 5402bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks SourceLocation DomLoc = CE->getArg(0)->getExprLoc(); 5412bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks StringRef DomName = C.getMacroNameOrSpelling(DomLoc); 5422bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks // White list the internal communication protocols. 5432bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") || 5442bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36")) 5452bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks return State; 5462bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks State = State->addTaint(CE, C.getLocationContext()); 5472bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks return State; 5482bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks} 5492bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks 5508bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE, 5519ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks CheckerContext &C) const { 5528bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 553259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 554259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return State; 555259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 556df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // All arguments except for the very first one should get taint. 557df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks for (unsigned int i = 1; i < CE->getNumArgs(); ++i) { 558df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // The arguments are pointer arguments. The data they are pointing at is 559df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks // tainted after the call. 560df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks const Expr* Arg = CE->getArg(i); 5617cdfe298ae49e381f6d78fc93855c372e5173dd0Anna Zaks SymbolRef Sym = getPointedToSymbol(C, Arg); 5621009ac715501a4fa1951d94722dcbe6ab30068f8Anna Zaks if (Sym) 5631009ac715501a4fa1951d94722dcbe6ab30068f8Anna Zaks State = State->addTaint(Sym); 5641009ac715501a4fa1951d94722dcbe6ab30068f8Anna Zaks } 5659ffbe243cca46082b4a59b5c3be454ab0c455378Anna Zaks return State; 566df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks} 567df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 5688bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE, 569259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks CheckerContext &C) const { 5705eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek return C.getState()->addTaint(CE, C.getLocationContext()); 571df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks} 572df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks 573b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaksbool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) { 5748bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 5755eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal Val = State->getSVal(E, C.getLocationContext()); 576efd6989f4644c8460854606e085fc69535054058Anna Zaks 577d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks // stdin is a pointer, so it would be a region. 578d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks const MemRegion *MemReg = Val.getAsRegion(); 579d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks 580d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks // The region should be symbolic, we do not know it's value. 581d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg); 582d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (!SymReg) 583efd6989f4644c8460854606e085fc69535054058Anna Zaks return false; 584efd6989f4644c8460854606e085fc69535054058Anna Zaks 585d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks // Get it's symbol and find the declaration region it's pointing to. 586d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol()); 587d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (!Sm) 588d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks return false; 589d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion()); 590d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (!DeclReg) 591d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks return false; 592efd6989f4644c8460854606e085fc69535054058Anna Zaks 593d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks // This region corresponds to a declaration, find out if it's a global/extern 594d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks // variable named stdin with the proper type. 595d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) { 596d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks D = D->getCanonicalDecl(); 597d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC()) 598d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (const PointerType * PtrTy = 599d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks dyn_cast<PointerType>(D->getType().getTypePtr())) 600d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks if (PtrTy->getPointeeType() == C.getASTContext().getFILEType()) 601d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks return true; 602d3d8548e75f3fb6db53ed0927c1df30d78f4ce1dAnna Zaks } 603efd6989f4644c8460854606e085fc69535054058Anna Zaks return false; 604efd6989f4644c8460854606e085fc69535054058Anna Zaks} 605efd6989f4644c8460854606e085fc69535054058Anna Zaks 6069f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaksstatic bool getPrintfFormatArgumentNum(const CallExpr *CE, 6079f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks const CheckerContext &C, 6089f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks unsigned int &ArgNum) { 6099f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Find if the function contains a format string argument. 6109f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf, 6119f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // vsnprintf, syslog, custom annotated functions. 6129f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks const FunctionDecl *FDecl = C.getCalleeDecl(CE); 6139f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks if (!FDecl) 6149f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return false; 615651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) { 6169f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks ArgNum = Format->getFormatIdx() - 1; 617caa5ab264ddea332e8423af1ebcea50d0cb37206Aaron Ballman if ((Format->getType()->getName() == "printf") && 618caa5ab264ddea332e8423af1ebcea50d0cb37206Aaron Ballman CE->getNumArgs() > ArgNum) 6199f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return true; 6209f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks } 6219f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 6229f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Or if a function is named setproctitle (this is a heuristic). 6239f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) { 6249f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks ArgNum = 0; 6259f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return true; 6269f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks } 6279f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 6289f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return false; 6299f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks} 6309f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 6318568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaksbool GenericTaintChecker::generateReportIfTainted(const Expr *E, 6328568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks const char Msg[], 6338568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks CheckerContext &C) const { 6348568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks assert(E); 6358568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6368568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks // Check for taint. 6378bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State = C.getState(); 6388568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (!State->isTainted(getPointedToSymbol(C, E)) && 6398568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks !State->isTainted(E, C.getLocationContext())) 6408568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return false; 6418568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6428568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks // Generate diagnostic. 6438568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (ExplodedNode *N = C.addTransition()) { 6448568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks initBugType(); 6458568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks BugReport *report = new BugReport(*BT, Msg, N); 6468568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks report->addRange(E->getSourceRange()); 647785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(report); 6488568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return true; 6498568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks } 6508568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return false; 6518568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks} 6528568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6539f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaksbool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE, 6549f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks CheckerContext &C) const{ 6559f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // Check if the function contains a format string argument. 6569f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks unsigned int ArgNum = 0; 6579f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks if (!getPrintfFormatArgumentNum(CE, C, ArgNum)) 6589f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return false; 6599f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 6609f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks // If either the format string content or the pointer itself are tainted, warn. 6618568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (generateReportIfTainted(CE->getArg(ArgNum), 6628568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks MsgUncontrolledFormatString, C)) 6638568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return true; 6648568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return false; 6658568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks} 6668568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6678568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaksbool GenericTaintChecker::checkSystemCall(const CallExpr *CE, 6688568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks StringRef Name, 6698568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks CheckerContext &C) const { 670b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks // TODO: It might make sense to run this check on demand. In some cases, 671b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks // we should check if the environment has been cleansed here. We also might 672b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks // need to know if the user was reset before these calls(seteuid). 6738568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks unsigned ArgNum = llvm::StringSwitch<unsigned>(Name) 6748568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks .Case("system", 0) 6758568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks .Case("popen", 0) 6762bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execl", 0) 6772bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execle", 0) 6782bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execlp", 0) 6792bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execv", 0) 6802bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execvp", 0) 6812bf8fd84087231fd92dfdebe18895e01a6ae405cAnna Zaks .Case("execvP", 0) 682b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("execve", 0) 683b9ac30cf9ec001fd0d63ffc44289a333a21e691dAnna Zaks .Case("dlopen", 0) 6848568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks .Default(UINT_MAX); 6858568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 686259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1)) 6878568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return false; 6888568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6898568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks if (generateReportIfTainted(CE->getArg(ArgNum), 6908568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks MsgSanitizeSystemArgs, C)) 6918568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks return true; 6928568ee743406ac4bb23c9768a0dffd627fdbc579Anna Zaks 6939f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks return false; 6949f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks} 6959f03b62036a7abc0a227b17f4a49b9eefced9450Anna Zaks 6964e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks// TODO: Should this check be a part of the CString checker? 6974e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks// If yes, should taint be a global setting? 6984e46221e38b7d434fbecb1cd56b259437206d246Anna Zaksbool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE, 6994e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks const FunctionDecl *FDecl, 7004e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks CheckerContext &C) const { 7014e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks // If the function has a buffer size argument, set ArgNum. 7024e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks unsigned ArgNum = InvalidArgIndex; 7034e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks unsigned BId = 0; 7044e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks if ( (BId = FDecl->getMemoryFunctionKind()) ) 7054e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks switch(BId) { 7064e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks case Builtin::BImemcpy: 7074e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks case Builtin::BImemmove: 7084e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks case Builtin::BIstrncpy: 7094e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 2; 7104e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks break; 7114e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks case Builtin::BIstrndup: 7124e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 1; 7134e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks break; 7144e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks default: 7154e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks break; 7164e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks }; 7174e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 7184e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks if (ArgNum == InvalidArgIndex) { 7194e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks if (C.isCLibraryFunction(FDecl, "malloc") || 7204e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks C.isCLibraryFunction(FDecl, "calloc") || 7214e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks C.isCLibraryFunction(FDecl, "alloca")) 7224e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 0; 7234e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks else if (C.isCLibraryFunction(FDecl, "memccpy")) 7244e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 3; 7254e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks else if (C.isCLibraryFunction(FDecl, "realloc")) 7264e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 1; 7274e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks else if (C.isCLibraryFunction(FDecl, "bcopy")) 7284e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks ArgNum = 2; 7294e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks } 7304e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 731259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum && 7324e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C)) 7334e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks return true; 7344e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 7354e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks return false; 7364e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks} 7374e46221e38b7d434fbecb1cd56b259437206d246Anna Zaks 738df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaksvoid ento::registerGenericTaintChecker(CheckerManager &mgr) { 739df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks mgr.registerChecker<GenericTaintChecker>(); 740df18c5ae6c48d3b56f7f9550875c53dc46eb8d78Anna Zaks} 741