CheckSecuritySyntaxOnly.cpp revision 590dd8e0959d8df5621827768987c4792b74fc06
19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//                     The LLVM Compiler Infrastructure
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// This file is distributed under the University of Illinois Open Source
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// License. See LICENSE.TXT for details.
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//  This file defines a set of flow-insensitive security checks.
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "ClangSACheckers.h"
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/Analysis/AnalysisContext.h"
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/AST/StmtVisitor.h"
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/Basic/TargetInfo.h"
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/StaticAnalyzer/Core/Checker.h"
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "llvm/ADT/StringSwitch.h"
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "llvm/Support/raw_ostream.h"
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonusing namespace clang;
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonusing namespace ento;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstatic bool isArc4RandomAvailable(const ASTContext &Ctx) {
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  return T.getVendor() == llvm::Triple::Apple ||
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         T.getOS() == llvm::Triple::FreeBSD ||
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         T.getOS() == llvm::Triple::NetBSD ||
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         T.getOS() == llvm::Triple::OpenBSD ||
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         T.getOS() == llvm::Triple::DragonFly;
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonnamespace {
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonclass WalkAST : public StmtVisitor<WalkAST> {
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BugReporter &BR;
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  AnalysisContext* AC;
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  enum { num_setids = 6 };
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  IdentifierInfo *II_setid[num_setids];
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const bool CheckRand;
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic:
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  WalkAST(BugReporter &br, AnalysisContext* ac)
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  : BR(br), AC(ac), II_setid(),
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    CheckRand(isArc4RandomAvailable(BR.getContext())) {}
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Statement visitor methods.
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void VisitCallExpr(CallExpr *CE);
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void VisitForStmt(ForStmt *S);
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void VisitCompoundStmt (CompoundStmt *S);
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void VisitStmt(Stmt *S) { VisitChildren(S); }
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void VisitChildren(Stmt *S);
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Helpers.
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  typedef void (WalkAST::*FnCheck)(const CallExpr *,
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson				   const FunctionDecl *);
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Checker-specific methods.
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkLoopConditionForFloat(const ForStmt *FS);
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkUncheckedReturnValue(CallExpr *CE);
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson};
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} // end anonymous namespace
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// AST walking.
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::VisitChildren(Stmt *S) {
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (Stmt *child = *I)
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Visit(child);
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::VisitCallExpr(CallExpr *CE) {
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Get the callee.
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionDecl *FD = CE->getDirectCallee();
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FD)
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Get the name of the callee. If it's a builtin, strip off the prefix.
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  IdentifierInfo *II = FD->getIdentifier();
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!II)   // if no identifier, not a simple C function
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  StringRef Name = II->getName();
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (Name.startswith("__builtin_"))
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Name = Name.substr(10);
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Set the evaluation function by switching on the callee name.
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("gets", &WalkAST::checkCall_gets)
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("getpw", &WalkAST::checkCall_getpw)
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("mktemp", &WalkAST::checkCall_mktemp)
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("drand48", &WalkAST::checkCall_rand)
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("erand48", &WalkAST::checkCall_rand)
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("jrand48", &WalkAST::checkCall_rand)
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("lrand48", &WalkAST::checkCall_rand)
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("mrand48", &WalkAST::checkCall_rand)
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("nrand48", &WalkAST::checkCall_rand)
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("lcong48", &WalkAST::checkCall_rand)
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("rand", &WalkAST::checkCall_rand)
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("rand_r", &WalkAST::checkCall_rand)
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Case("random", &WalkAST::checkCall_random)
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    .Default(NULL);
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // If the callee isn't defined, it is not of security concern.
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Check and evaluate the call.
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (evalFunction)
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    (this->*evalFunction)(CE, FD);
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Recurse and check children.
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  VisitChildren(CE);
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::VisitCompoundStmt(CompoundStmt *S) {
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (Stmt *child = *I) {
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (CallExpr *CE = dyn_cast<CallExpr>(child))
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        checkUncheckedReturnValue(CE);
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Visit(child);
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::VisitForStmt(ForStmt *FS) {
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  checkLoopConditionForFloat(FS);
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Recurse and check children.
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  VisitChildren(FS);
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: floating poing variable used as loop counter.
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Originally: <rdar://problem/6336718>
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Implements: CERT security coding advisory FLP-30.
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonstatic const DeclRefExpr*
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsongetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  expr = expr->IgnoreParenCasts();
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          B->getOpcode() == BO_Comma))
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return NULL;
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return lhs;
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return rhs;
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return NULL;
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    const NamedDecl *ND = DR->getDecl();
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return ND == x || ND == y ? DR : NULL;
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return U->isIncrementDecrementOp()
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      ? getIncrementedVar(U->getSubExpr(), x, y) : NULL;
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  return NULL;
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/// CheckLoopConditionForFloat - This check looks for 'for' statements that
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson///  use a floating point variable as a loop counter.
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson///  CERT: FLP30-C, FLP30-CPP.
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson///
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Does the loop have a condition?
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const Expr *condition = FS->getCond();
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!condition)
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Does the loop have an increment?
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const Expr *increment = FS->getInc();
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!increment)
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Strip away '()' and casts.
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  condition = condition->IgnoreParenCasts();
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  increment = increment->IgnoreParenCasts();
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Is the loop condition a comparison?
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!B)
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Is this a comparison?
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!(B->isRelationalOp() || B->isEqualityOp()))
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Are we comparing variables?
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const DeclRefExpr *drLHS =
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const DeclRefExpr *drRHS =
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Does at least one of the variables have a floating point type?
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : NULL;
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : NULL;
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!drLHS && !drRHS)
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!vdLHS && !vdRHS)
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Does either variable appear in increment?
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!drInc)
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Emit the error.  First figure out which DeclRefExpr in the condition
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // referenced the compared variable.
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SmallVector<SourceRange, 2> ranges;
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::SmallString<256> sbuf;
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::raw_svector_ostream os(sbuf);
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  os << "Variable '" << drCond->getDecl()->getName()
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     << "' with floating point type '" << drCond->getType().getAsString()
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     << "' should not be used as a loop counter";
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  ranges.push_back(drCond->getSourceRange());
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  ranges.push_back(drInc->getSourceRange());
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const char *bugType = "Floating point variable used as loop counter";
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation FSLoc =
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport(bugType, "Security", os.str(),
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     FSLoc, ranges.data(), ranges.size());
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Any use of 'gets' is insecure.
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Originally: <rdar://problem/6335715>
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-242: Use of Inherently Dangerous Function
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FPT
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FPT)
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the function takes a single argument.
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FPT->getNumArgs() != 1)
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Is the argument a 'char*'?
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!PT)
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("Potential buffer overflow in call to 'gets'",
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Security",
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Call to function 'gets' is extremely insecure as it can "
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "always result in a buffer overflow",
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     CELoc, &R, 1);
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Any use of 'getpwd' is insecure.
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-477: Use of Obsolete Functions
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FPT
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FPT)
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the function takes two arguments.
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FPT->getNumArgs() != 2)
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify the first argument type is integer.
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FPT->getArgType(0)->isIntegerType())
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify the second argument type is char*.
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(1));
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!PT)
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("Potential buffer overflow in call to 'getpw'",
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Security",
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "The getpw() function is dangerous as it may overflow the "
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "provided buffer. It is obsoleted by getpwuid().",
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     CELoc, &R, 1);
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Any use of 'mktemp' is insecure.It is obsoleted by mkstemp().
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-377: Insecure Temporary File
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FPT
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if(!FPT)
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the function takes a single argument.
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FPT->getNumArgs() != 1)
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the argument is Pointer Type.
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!PT)
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the argument is a 'char*'.
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a waring.
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Security",
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Call to function 'mktemp' is insecure as it always "
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "creates or uses insecure temporary file.  Use 'mkstemp' instead",
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     CELoc, &R, 1);
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Any use of 'strcpy' is insecure.
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-119: Improper Restriction of Operations within
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// the Bounds of a Memory Buffer
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!checkCall_strCommon(CE, FD))
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in "
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "call 'strcpy'",
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Security",
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Call to function 'strcpy' is insecure as it does not "
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "provide bounding of the memory buffer. Replace "
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "unbounded copy functions with analogous functions that "
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "support length arguments such as 'strncpy'. CWE-119.",
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     CELoc, &R, 1);
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Any use of 'strcat' is insecure.
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-119: Improper Restriction of Operations within
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// the Bounds of a Memory Buffer
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!checkCall_strCommon(CE, FD))
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in "
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "call 'strcat'",
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "Security",
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "Call to function 'strcat' is insecure as it does not "
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "provide bounding of the memory buffer. Replace "
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "unbounded copy functions with analogous functions that "
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		     "support length arguments such as 'strncat'. CWE-119.",
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     CELoc, &R, 1);
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Common check for str* functions with no bounds parameters.
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonbool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FPT
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FPT)
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return false;
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify the function takes two arguments, three in the _chk version.
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int numArgs = FPT->getNumArgs();
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (numArgs != 2 && numArgs != 3)
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return false;
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify the type for both arguments.
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (int i = 0; i < 2; i++) {
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Verify that the arguments are pointers.
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(i));
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (!PT)
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return false;
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Verify that the argument is a 'char*'.
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return false;
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  return true;
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Linear congruent random number generators should not be used
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Originally: <rdar://problem/63371000>
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// CWE-338: Use of cryptographically weak prng
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!CheckRand)
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FTP
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FTP)
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FTP->getNumArgs() == 1) {
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Is the argument an 'unsigned short *'?
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (Actually any integer type is allowed.)
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (!PT)
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return;
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (! PT->getPointeeType()->isIntegerType())
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return;
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  else if (FTP->getNumArgs() != 0)
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::SmallString<256> buf1;
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::raw_svector_ostream os1(buf1);
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  os1 << '\'' << FD << "' is a poor random number generator";
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::SmallString<256> buf2;
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::raw_svector_ostream os2(buf2);
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  os2 << "Function '" << FD
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      << "' is obsolete because it implements a poor random number generator."
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      << "  Use 'arc4random' instead";
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1);
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: 'random' should not be used
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Originally: <rdar://problem/63371000>
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!CheckRand)
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FTP
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FTP)
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the function takes no argument.
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FTP->getNumArgs() != 0)
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport("'random' is not a secure random number generator",
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "Security",
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "The 'random' function produces a sequence of values that "
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "an adversary may be able to predict.  Use 'arc4random' "
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     "instead", CELoc, &R, 1);
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Check: Should check whether privileges are dropped successfully.
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// Originally: <rdar://problem/6337132>
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionDecl *FD = CE->getDirectCallee();
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FD)
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (II_setid[0] == NULL) {
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static const char * const identifiers[num_setids] = {
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      "setuid", "setgid", "seteuid", "setegid",
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      "setreuid", "setregid"
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    };
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    for (size_t i = 0; i < num_setids; i++)
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const IdentifierInfo *id = FD->getIdentifier();
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  size_t identifierid;
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (identifierid = 0; identifierid < num_setids; identifierid++)
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (id == II_setid[identifierid])
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      break;
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (identifierid >= num_setids)
5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const FunctionProtoType *FTP
5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (!FTP)
5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Verify that the function takes one or two arguments (depending on
5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  //   the function).
5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  if (FTP->getNumArgs() != (identifierid < 4 ? 1 : 2))
5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return;
5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // The arguments must be integers.
5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (unsigned i = 0; i < FTP->getNumArgs(); i++)
5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (! FTP->getArgType(i)->isIntegerType())
5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return;
5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Issue a warning.
5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::SmallString<256> buf1;
5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::raw_svector_ostream os1(buf1);
5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  os1 << "Return value is not checked in call to '" << FD << '\'';
5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::SmallString<256> buf2;
5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  llvm::raw_svector_ostream os2(buf2);
5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  os2 << "The return value from the call to '" << FD
5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      << "' is not checked.  If an error occurs in '" << FD
5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      << "', the following code may execute with unexpected privileges";
5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  SourceRange R = CE->getCallee()->getSourceRange();
5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PathDiagnosticLocation CELoc =
5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1);
5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// SecuritySyntaxChecker
5859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//===----------------------------------------------------------------------===//
5869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonnamespace {
5889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonclass SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
5899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic:
5909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
5919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        BugReporter &BR) const {
5929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    WalkAST walker(BR, mgr.getAnalysisContext(D));
5939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    walker.Visit(D->getBody());
5949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson};
5969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
5979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonvoid ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
5999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  mgr.registerChecker<SecuritySyntaxChecker>();
6009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
6019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson