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"
2687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar#include "llvm/ADT/APSInt.h"
2717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek#include "llvm/ADT/SmallVector.h"
284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include <utility>
2917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
3017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekusing namespace clang;
3117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekusing namespace ento;
3287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarusing llvm::APSInt;
3317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
3417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremeneknamespace {
3517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekstruct MallocOverflowCheck {
3617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  const BinaryOperator *mulop;
3717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  const Expr *variable;
3887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  APSInt maxVal;
3917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
4087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  MallocOverflowCheck(const BinaryOperator *m, const Expr *v, APSInt val)
414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      : mulop(m), variable(v), maxVal(std::move(val)) {}
4217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek};
4317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
4417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekclass MallocOverflowSecurityChecker : public Checker<check::ASTCodeBody> {
4517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekpublic:
4617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  void checkASTCodeBody(const Decl *D, AnalysisManager &mgr,
4717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek                        BugReporter &BR) const;
4817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
4917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  void CheckMallocArgument(
50cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
5117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    const Expr *TheArgument, ASTContext &Context) const;
5217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
5317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  void OutputPossibleOverflows(
54cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
5517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    const Decl *D, BugReporter &BR, AnalysisManager &mgr) const;
5617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
5717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek};
5817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek} // end anonymous namespace
5917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
6087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar// Return true for computations which evaluate to zero: e.g., mult by 0.
6187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstatic inline bool EvaluatesToZero(APSInt &Val, BinaryOperatorKind op) {
6287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return (op == BO_Mul) && (Val == 0);
6387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar}
6487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
6517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::CheckMallocArgument(
66cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
6717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  const Expr *TheArgument,
6817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  ASTContext &Context) const {
6917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
7017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  /* Look for a linear combination with a single variable, and at least
7117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek   one multiplication.
7217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek   Reject anything that applies to the variable: an explicit cast,
7317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek   conditional expression, an operation that could reduce the range
7417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek   of the result, or anything too complicated :-).  */
7587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  const Expr *e = TheArgument;
766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const BinaryOperator * mulop = nullptr;
7787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  APSInt maxVal;
7817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
7917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  for (;;) {
8087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    maxVal = 0;
8117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    e = e->IgnoreParenImpCasts();
8287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    if (const BinaryOperator *binop = dyn_cast<BinaryOperator>(e)) {
8317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      BinaryOperatorKind opc = binop->getOpcode();
8417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      // TODO: ignore multiplications by 1, reject if multiplied by 0.
856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (mulop == nullptr && opc == BO_Mul)
8617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        mulop = binop;
8717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl)
8817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        return;
8917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
9017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      const Expr *lhs = binop->getLHS();
9117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      const Expr *rhs = binop->getRHS();
9287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (rhs->isEvaluatable(Context)) {
9317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        e = lhs;
9487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        maxVal = rhs->EvaluateKnownConstInt(Context);
9587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        if (EvaluatesToZero(maxVal, opc))
9687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          return;
9787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      } else if ((opc == BO_Add || opc == BO_Mul) &&
9887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                 lhs->isEvaluatable(Context)) {
9987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        maxVal = lhs->EvaluateKnownConstInt(Context);
10087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        if (EvaluatesToZero(maxVal, opc))
10187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          return;
10217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        e = rhs;
10387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      } else
10417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        return;
10517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
10617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
10717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      break;
10817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    else
10917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      return;
11017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  }
11117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
1126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (mulop == nullptr)
11317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    return;
11417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
11517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  //  We've found the right structure of malloc argument, now save
11617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // the data so when the body of the function is completely available
11717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // we can check for comparisons.
11817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
11917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // TODO: Could push this into the innermost scope where 'e' is
12017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // defined, rather than the whole function.
12187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e, maxVal));
12217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}
12317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
12417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremeneknamespace {
12517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// A worker class for OutputPossibleOverflows.
12617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekclass CheckOverflowOps :
12717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  public EvaluatedExprVisitor<CheckOverflowOps> {
12817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekpublic:
129cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  typedef SmallVectorImpl<MallocOverflowCheck> theVecType;
13017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
13117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekprivate:
13217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    theVecType &toScanFor;
13317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    ASTContext &Context;
13417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
13517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    bool isIntZeroExpr(const Expr *E) const {
136a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith      if (!E->getType()->isIntegralOrEnumerationType())
137a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith        return false;
138a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith      llvm::APSInt Result;
139a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith      if (E->EvaluateAsInt(Result, Context))
140a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith        return Result == 0;
141a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith      return false;
14217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
14317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
1444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    static const Decl *getDecl(const DeclRefExpr *DR) { return DR->getDecl(); }
1454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    static const Decl *getDecl(const MemberExpr *ME) {
1464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return ME->getMemberDecl();
1474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
14817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
14987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    template <typename T1>
1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    void Erase(const T1 *DR,
1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar               llvm::function_ref<bool(const MallocOverflowCheck &)> Pred) {
1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      auto P = [DR, Pred](const MallocOverflowCheck &Check) {
1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (const auto *CheckDR = dyn_cast<T1>(Check.variable))
1544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar          return getDecl(CheckDR) == getDecl(DR) && Pred(Check);
1554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        return false;
1564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      };
1574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      toScanFor.erase(std::remove_if(toScanFor.begin(), toScanFor.end(), P),
1584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar                      toScanFor.end());
15987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
16087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
16187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    void CheckExpr(const Expr *E_p) {
1624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      auto PredTrue = [](const MallocOverflowCheck &) { return true; };
16387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const Expr *E = E_p->IgnoreParenImpCasts();
16487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
16587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Erase<DeclRefExpr>(DR, PredTrue);
16658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar      else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
16787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Erase<MemberExpr>(ME, PredTrue);
16887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      }
16987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
17087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
17187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // Check if the argument to malloc is assigned a value
17287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // which cannot cause an overflow.
17387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // e.g., malloc (mul * x) and,
17487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // case 1: mul = <constant value>
17587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    // case 2: mul = a/b, where b > x
17687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    void CheckAssignmentExpr(BinaryOperator *AssignEx) {
17787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      bool assignKnown = false;
17887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      bool numeratorKnown = false, denomKnown = false;
17987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      APSInt denomVal;
18087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      denomVal = 0;
18187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
18287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // Erase if the multiplicand was assigned a constant value.
18387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const Expr *rhs = AssignEx->getRHS();
18487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (rhs->isEvaluatable(Context))
18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        assignKnown = true;
18687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
18787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // Discard the report if the multiplicand was assigned a value,
18887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // that can never overflow after multiplication. e.g., the assignment
18987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // is a division operator and the denominator is > other multiplicand.
19087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const Expr *rhse = rhs->IgnoreParenImpCasts();
19187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) {
19287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        if (BOp->getOpcode() == BO_Div) {
19387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts();
19487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          if (denom->EvaluateAsInt(denomVal, Context))
19587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            denomKnown = true;
19687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts();
19787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          if (numerator->isEvaluatable(Context))
19887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            numeratorKnown = true;
19917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        }
20017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      }
20187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (!assignKnown && !denomKnown)
20287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return;
20387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      auto denomExtVal = denomVal.getExtValue();
20487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
20587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // Ignore negative denominator.
20687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (denomExtVal < 0)
20787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return;
20887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
20987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const Expr *lhs = AssignEx->getLHS();
21087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      const Expr *E = lhs->IgnoreParenImpCasts();
21187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
21287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      auto pred = [assignKnown, numeratorKnown,
2134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar                   denomExtVal](const MallocOverflowCheck &Check) {
21487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return assignKnown ||
2154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar               (numeratorKnown && (denomExtVal >= Check.maxVal.getExtValue()));
21687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      };
21787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
21887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
21987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Erase<DeclRefExpr>(DR, pred);
22087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      else if (const auto *ME = dyn_cast<MemberExpr>(E))
22187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        Erase<MemberExpr>(ME, pred);
22217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
22317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
22417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  public:
22517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    void VisitBinaryOperator(BinaryOperator *E) {
22617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      if (E->isComparisonOp()) {
22717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        const Expr * lhs = E->getLHS();
22817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        const Expr * rhs = E->getRHS();
22917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        // Ignore comparisons against zero, since they generally don't
23017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        // protect against an overflow.
23187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        if (!isIntZeroExpr(lhs) && !isIntZeroExpr(rhs)) {
23217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          CheckExpr(lhs);
23317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          CheckExpr(rhs);
23417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        }
23517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      }
23687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (E->isAssignmentOp())
23787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        CheckAssignmentExpr(E);
23817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      EvaluatedExprVisitor<CheckOverflowOps>::VisitBinaryOperator(E);
23917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
24017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
24117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    /* We specifically ignore loop conditions, because they're typically
24217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek     not error checks.  */
24317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    void VisitWhileStmt(WhileStmt *S) {
24417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      return this->Visit(S->getBody());
24517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
24617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    void VisitForStmt(ForStmt *S) {
24717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      return this->Visit(S->getBody());
24817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
24917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    void VisitDoStmt(DoStmt *S) {
25017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      return this->Visit(S->getBody());
25117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
25217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
25317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    CheckOverflowOps(theVecType &v, ASTContext &ctx)
25417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    : EvaluatedExprVisitor<CheckOverflowOps>(ctx),
25517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      toScanFor(v), Context(ctx)
25617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    { }
25717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  };
25817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}
25917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
26017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// OutputPossibleOverflows - We've found a possible overflow earlier,
26117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// now check whether Body might contain a comparison which might be
26217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// preventing the overflow.
26317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// This doesn't do flow analysis, range analysis, or points-to analysis; it's
26417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// just a dumb "is there a comparison" scan.  The aim here is to
26517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// detect the most blatent cases of overflow and educate the
26617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek// programmer.
26717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::OutputPossibleOverflows(
268cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
26917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  const Decl *D, BugReporter &BR, AnalysisManager &mgr) const {
27017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // By far the most common case: nothing to check.
27117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  if (PossibleMallocOverflows.empty())
27217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    return;
27317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
27417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // Delete any possible overflows which have a comparison.
27517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  CheckOverflowOps c(PossibleMallocOverflows, BR.getContext());
2761d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  c.Visit(mgr.getAnalysisDeclContext(D)->getBody());
27717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
27817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // Output warnings for all overflows that are left.
27917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  for (CheckOverflowOps::theVecType::iterator
28017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek       i = PossibleMallocOverflows.begin(),
28117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek       e = PossibleMallocOverflows.end();
28217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek       i != e;
28317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek       ++i) {
284651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BR.EmitBasicReport(
285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        D, this, "malloc() size overflow", categories::UnixAPI,
286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        "the computation of the size of the memory allocation may overflow",
287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        PathDiagnosticLocation::createOperatorLoc(i->mulop,
288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                  BR.getSourceManager()),
289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        i->mulop->getSourceRange());
29017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  }
29117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}
29217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
29317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenekvoid MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D,
29417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek                                             AnalysisManager &mgr,
29517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek                                             BugReporter &BR) const {
29617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
29717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  CFG *cfg = mgr.getCFG(D);
29817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  if (!cfg)
29917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    return;
30017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
30117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  // A list of variables referenced in possibly overflowing malloc operands.
302cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  SmallVector<MallocOverflowCheck, 2> PossibleMallocOverflows;
30317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
30417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  for (CFG::iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
30517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    CFGBlock *block = *it;
30617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    for (CFGBlock::iterator bi = block->begin(), be = block->end();
30717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek         bi != be; ++bi) {
308b07805485c603be3d8011f72611465324c9e664bDavid Blaikie      if (Optional<CFGStmt> CS = bi->getAs<CFGStmt>()) {
309b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
31017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          // Get the callee.
31117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          const FunctionDecl *FD = TheCall->getDirectCallee();
31217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
31317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          if (!FD)
31487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            continue;
31517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
31617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          // Get the name of the callee. If it's a builtin, strip off the prefix.
31717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          IdentifierInfo *FnInfo = FD->getIdentifier();
3187e5f112ca7410af93c7cdc07cf3a9dae15214300Anna Zaks          if (!FnInfo)
31987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            continue;
32017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
32117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) {
32217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek            if (TheCall->getNumArgs() == 1)
32317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek              CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
32417f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek                                  mgr.getASTContext());
32517f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek          }
32617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek        }
32717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek      }
32817f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek    }
32917f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  }
33017f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
33117f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
33217f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}
33317f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek
334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid
335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) {
33617f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek  mgr.registerChecker<MallocOverflowSecurityChecker>();
33717f7bdddd11a2dc5b4be248f756e14b1ebfe207bTed Kremenek}
338