MallocOverflowSecurityChecker.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// MallocOverflowSecurityChecker.cpp - Check for malloc overflows -*- C++ -*-=// 217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// 317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// The LLVM Compiler Infrastructure 417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// 517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// This file is distributed under the University of Illinois Open Source 617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// License. See LICENSE.TXT for details. 717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// 817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek//===----------------------------------------------------------------------===// 917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// 1017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// This checker detects a common memory allocation security flaw. 1117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// Suppose 'unsigned int n' comes from an untrusted source. If the 1217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// code looks like 'malloc (n * 4)', and an attacker can make 'n' be 1317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// say MAX_UINT/4+2, then instead of allocating the correct 'n' 4-byte 1417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// elements, this will actually allocate only two because of overflow. 1517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// Then when the rest of the program attempts to store values past the 1617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// second element, these values will actually overwrite other items in 1717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// the heap, probably allowing the attacker to execute arbitrary code. 1817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// 1917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek//===----------------------------------------------------------------------===// 2017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 2117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek#include "ClangSACheckers.h" 2217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek#include "clang/AST/EvaluatedExprVisitor.h" 2317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/Checker.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 2617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek#include "llvm/ADT/SmallVector.h" 2717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 2817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekusing namespace clang; 2917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekusing namespace ento; 3017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 3117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremeneknamespace { 3217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekstruct MallocOverflowCheck { 3317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const BinaryOperator *mulop; 3417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *variable; 3517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 3617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek MallocOverflowCheck (const BinaryOperator *m, const Expr *v) 3717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek : mulop(m), variable (v) 3817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek {} 3917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}; 4017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 4117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekclass MallocOverflowSecurityChecker : public Checker<check::ASTCodeBody> { 4217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekpublic: 4317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void checkASTCodeBody(const Decl *D, AnalysisManager &mgr, 4417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek BugReporter &BR) const; 4517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 4617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void CheckMallocArgument( 47cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, 4817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *TheArgument, ASTContext &Context) const; 4917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 5017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void OutputPossibleOverflows( 51cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, 5217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Decl *D, BugReporter &BR, AnalysisManager &mgr) const; 5317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 5417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}; 5517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} // end anonymous namespace 5617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 5717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::CheckMallocArgument( 58cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, 5917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *TheArgument, 6017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek ASTContext &Context) const { 6117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 6217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek /* Look for a linear combination with a single variable, and at least 6317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek one multiplication. 6417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek Reject anything that applies to the variable: an explicit cast, 6517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek conditional expression, an operation that could reduce the range 6617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek of the result, or anything too complicated :-). */ 6717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr * e = TheArgument; 6817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const BinaryOperator * mulop = NULL; 6917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 7017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek for (;;) { 7117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek e = e->IgnoreParenImpCasts(); 7217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (isa<BinaryOperator>(e)) { 7317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const BinaryOperator * binop = dyn_cast<BinaryOperator>(e); 7417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek BinaryOperatorKind opc = binop->getOpcode(); 7517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // TODO: ignore multiplications by 1, reject if multiplied by 0. 7617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (mulop == NULL && opc == BO_Mul) 7717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek mulop = binop; 7817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl) 7917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 8017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 8117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *lhs = binop->getLHS(); 8217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *rhs = binop->getRHS(); 8317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (rhs->isEvaluatable(Context)) 8417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek e = lhs; 8517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek else if ((opc == BO_Add || opc == BO_Mul) 8617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek && lhs->isEvaluatable(Context)) 8717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek e = rhs; 8817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek else 8917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 9017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 9117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e)) 9217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek break; 9317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek else 9417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 9517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 9617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 9717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (mulop == NULL) 9817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 9917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 10017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // We've found the right structure of malloc argument, now save 10117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // the data so when the body of the function is completely available 10217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // we can check for comparisons. 10317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 10417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // TODO: Could push this into the innermost scope where 'e' is 10517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // defined, rather than the whole function. 10617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e)); 10717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} 10817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 10917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremeneknamespace { 11017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// A worker class for OutputPossibleOverflows. 11117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekclass CheckOverflowOps : 11217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek public EvaluatedExprVisitor<CheckOverflowOps> { 11317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekpublic: 114cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko typedef SmallVectorImpl<MallocOverflowCheck> theVecType; 11517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 11617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekprivate: 11717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek theVecType &toScanFor; 11817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek ASTContext &Context; 11917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 12017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek bool isIntZeroExpr(const Expr *E) const { 121a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith if (!E->getType()->isIntegralOrEnumerationType()) 122a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith return false; 123a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith llvm::APSInt Result; 124a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith if (E->EvaluateAsInt(Result, Context)) 125a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith return Result == 0; 126a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith return false; 12717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 12817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 12917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void CheckExpr(const Expr *E_p) { 13017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr *E = E_p->IgnoreParenImpCasts(); 13117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 13217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek theVecType::iterator i = toScanFor.end(); 13317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek theVecType::iterator e = toScanFor.begin(); 13417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 13517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) { 13617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Decl * EdreD = DR->getDecl(); 13717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek while (i != e) { 13817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek --i; 13917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (const DeclRefExpr *DR_i = dyn_cast<DeclRefExpr>(i->variable)) { 14017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (DR_i->getDecl() == EdreD) 14117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek i = toScanFor.erase(i); 14217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 14317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 14417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 14517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek else if (isa<MemberExpr>(E)) { 14617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // No points-to analysis, just look at the member 14717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Decl * EmeMD = dyn_cast<MemberExpr>(E)->getMemberDecl(); 14817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek while (i != e) { 14917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek --i; 15017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (isa<MemberExpr>(i->variable)) { 15117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (dyn_cast<MemberExpr>(i->variable)->getMemberDecl() == EmeMD) 15217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek i = toScanFor.erase (i); 15317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 15417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 15517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 15617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 15717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 15817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek public: 15917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void VisitBinaryOperator(BinaryOperator *E) { 16017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (E->isComparisonOp()) { 16117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr * lhs = E->getLHS(); 16217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Expr * rhs = E->getRHS(); 16317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // Ignore comparisons against zero, since they generally don't 16417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // protect against an overflow. 16517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (!isIntZeroExpr(lhs) && ! isIntZeroExpr(rhs)) { 16617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CheckExpr(lhs); 16717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CheckExpr(rhs); 16817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 16917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 17017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek EvaluatedExprVisitor<CheckOverflowOps>::VisitBinaryOperator(E); 17117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 17217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 17317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek /* We specifically ignore loop conditions, because they're typically 17417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek not error checks. */ 17517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void VisitWhileStmt(WhileStmt *S) { 17617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return this->Visit(S->getBody()); 17717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 17817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void VisitForStmt(ForStmt *S) { 17917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return this->Visit(S->getBody()); 18017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 18117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek void VisitDoStmt(DoStmt *S) { 18217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return this->Visit(S->getBody()); 18317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 18417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 18517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CheckOverflowOps(theVecType &v, ASTContext &ctx) 18617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek : EvaluatedExprVisitor<CheckOverflowOps>(ctx), 18717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek toScanFor(v), Context(ctx) 18817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek { } 18917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek }; 19017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} 19117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 19217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// OutputPossibleOverflows - We've found a possible overflow earlier, 19317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// now check whether Body might contain a comparison which might be 19417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// preventing the overflow. 19517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// This doesn't do flow analysis, range analysis, or points-to analysis; it's 19617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// just a dumb "is there a comparison" scan. The aim here is to 19717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// detect the most blatent cases of overflow and educate the 19817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// programmer. 19917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::OutputPossibleOverflows( 200cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, 20117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const Decl *D, BugReporter &BR, AnalysisManager &mgr) const { 20217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // By far the most common case: nothing to check. 20317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (PossibleMallocOverflows.empty()) 20417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 20517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 20617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // Delete any possible overflows which have a comparison. 20717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CheckOverflowOps c(PossibleMallocOverflows, BR.getContext()); 2081d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek c.Visit(mgr.getAnalysisDeclContext(D)->getBody()); 20917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 21017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // Output warnings for all overflows that are left. 21117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek for (CheckOverflowOps::theVecType::iterator 21217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek i = PossibleMallocOverflows.begin(), 21317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek e = PossibleMallocOverflows.end(); 21417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek i != e; 21517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek ++i) { 216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.EmitBasicReport( 217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines D, this, "malloc() size overflow", categories::UnixAPI, 218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "the computation of the size of the memory allocation may overflow", 219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PathDiagnosticLocation::createOperatorLoc(i->mulop, 220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.getSourceManager()), 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines i->mulop->getSourceRange()); 22217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 22317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} 22417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 22517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D, 22617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek AnalysisManager &mgr, 22717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek BugReporter &BR) const { 22817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 22917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CFG *cfg = mgr.getCFG(D); 23017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (!cfg) 23117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 23217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 23317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // A list of variables referenced in possibly overflowing malloc operands. 234cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<MallocOverflowCheck, 2> PossibleMallocOverflows; 23517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 23617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek for (CFG::iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) { 23717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CFGBlock *block = *it; 23817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek for (CFGBlock::iterator bi = block->begin(), be = block->end(); 23917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek bi != be; ++bi) { 240b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = bi->getAs<CFGStmt>()) { 241b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) { 24217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // Get the callee. 24317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek const FunctionDecl *FD = TheCall->getDirectCallee(); 24417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 24517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (!FD) 24617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek return; 24717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 24817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek // Get the name of the callee. If it's a builtin, strip off the prefix. 24917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek IdentifierInfo *FnInfo = FD->getIdentifier(); 2507e5f112ca7410af93c7cdc07cf3a9dae15214300Anna Zaks if (!FnInfo) 2517e5f112ca7410af93c7cdc07cf3a9dae15214300Anna Zaks return; 25217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 25317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) { 25417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek if (TheCall->getNumArgs() == 1) 25517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0), 25617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek mgr.getASTContext()); 25717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 25817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 25917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 26017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 26117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek } 26217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 26317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr); 26417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} 26517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek 266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid 267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) { 26817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek mgr.registerChecker<MallocOverflowSecurityChecker>(); 26917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} 270