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