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