MacOSKeychainAPIChecker.cpp revision 065a4055f796c545cdcc89a490be2d3288426d57
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//==--- MacOSKeychainAPIChecker.cpp ------------------------------*- C++ -*-==//
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// License. See LICENSE.TXT for details.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===//
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This checker flags misuses of KeyChainAPI. In particular, the password data
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// allocated/returned by SecKeychainItemCopyContent,
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SecKeychainFindGenericPassword, SecKeychainFindInternetPassword functions has
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// to be freed using a call to SecKeychainItemFreeContent.
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===//
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ClangSACheckers.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace ento;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MacOSKeychainAPIChecker : public Checker<check::PreStmt<CallExpr>,
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               check::PreStmt<ReturnStmt>,
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               check::PostStmt<CallExpr>,
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               check::EndPath,
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               check::DeadSymbols> {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mutable llvm::OwningPtr<BugType> BT;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// AllocationState is a part of the checker specific state together with the
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// MemRegion corresponding to the allocated data.
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct AllocationState {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /// The index of the allocator function.
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned int AllocatorIdx;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SymbolRef Region;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AllocationState(const Expr *E, unsigned int Idx, SymbolRef R) :
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AllocatorIdx(Idx),
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Region(R) {}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool operator==(const AllocationState &X) const {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return (AllocatorIdx == X.AllocatorIdx &&
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              Region == X.Region);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void Profile(llvm::FoldingSetNodeID &ID) const {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ID.AddInteger(AllocatorIdx);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ID.AddPointer(Region);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkPostStmt(const CallExpr *S, CheckerContext &C) const;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)private:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::pair<SymbolRef, const AllocationState*> AllocationPair;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef llvm::SmallVector<AllocationPair, 2> AllocationPairVec;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum APIKind {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /// Denotes functions tracked by this checker.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ValidAPI = 0,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /// The functions commonly/mistakenly used in place of the given API.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ErrorAPI = 1,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /// The functions which may allocate the data. These are tracked to reduce
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /// the false alarm rate.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PossibleAPI = 2
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// Stores the information about the allocator and deallocator functions -
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// these are the functions the checker is tracking.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct ADFunctionInfo {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* Name;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int Param;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int DeallocatorIdx;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    APIKind Kind;
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static const unsigned InvalidIdx = 100000;
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static const unsigned FunctionsToTrackSize = 8;
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static const ADFunctionInfo FunctionsToTrack[FunctionsToTrackSize];
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  /// The value, which represents no error return value for allocator functions.
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static const unsigned NoErr = 0;
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  /// Given the function name, returns the index of the allocator/deallocator
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  /// function.
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static unsigned getTrackedFunctionIndex(StringRef Name, bool IsAllocator);
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  inline void initBugType() const {
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!BT)
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      BT.reset(new BugType("Improper use of SecKeychain API", "Mac OS API"));
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void generateDeallocatorMismatchReport(const AllocationPair &AP,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const Expr *ArgExpr,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         CheckerContext &C) const;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BugReport *generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    ExplodedNode *N) const;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// Check if RetSym evaluates to an error value in the current state.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool definitelyReturnedError(SymbolRef RetSym,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const ProgramState *State,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               SValBuilder &Builder,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bool noError = false) const;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// Check if RetSym evaluates to a NoErr value in the current state.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool definitelyDidnotReturnError(SymbolRef RetSym,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const ProgramState *State,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   SValBuilder &Builder) const {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return definitelyReturnedError(RetSym, State, Builder, true);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// The bug visitor which allows us to print extra diagnostics along the
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// BugReport path. For example, showing the allocation site of the leaked
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /// region.
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class SecKeychainBugVisitor : public BugReporterVisitor {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  protected:
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The allocated region symbol tracked by the main analysis.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SymbolRef Sym;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~SecKeychainBugVisitor() {}
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void Profile(llvm::FoldingSetNodeID &ID) const {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static int X = 0;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ID.AddPointer(&X);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ID.AddPointer(Sym);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const ExplodedNode *PrevN,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   BugReporterContext &BRC,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   BugReport &BR);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// ProgramState traits to store the currently allocated (and not yet freed)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// symbols. This is a map from the allocated content symbol to the
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// corresponding AllocationState.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef llvm::ImmutableMap<SymbolRef,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       MacOSKeychainAPIChecker::AllocationState> AllocatedSetTy;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { struct AllocatedData {}; }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace clang { namespace ento {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<> struct ProgramStateTrait<AllocatedData>
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    :  public ProgramStatePartialTrait<AllocatedSetTy > {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void *GDMIndex() { static int index = 0; return &index; }
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool isEnclosingFunctionParam(const Expr *E) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  E = E->IgnoreParenCasts();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ValueDecl *VD = DRE->getDecl();
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (isa<ImplicitParamDecl>(VD) || isa<ParmVarDecl>(VD))
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const MacOSKeychainAPIChecker::ADFunctionInfo
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MacOSKeychainAPIChecker::FunctionsToTrack[FunctionsToTrackSize] = {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"SecKeychainItemCopyContent", 4, 3, ValidAPI},                       // 0
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"SecKeychainFindGenericPassword", 6, 3, ValidAPI},                   // 1
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    {"SecKeychainFindInternetPassword", 13, 3, ValidAPI},                 // 2
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"SecKeychainItemFreeContent", 1, InvalidIdx, ValidAPI},              // 3
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"SecKeychainItemCopyAttributesAndData", 5, 5, ValidAPI},             // 4
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"SecKeychainItemFreeAttributesAndData", 1, InvalidIdx, ValidAPI},    // 5
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"free", 0, InvalidIdx, ErrorAPI},                                    // 6
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {"CFStringCreateWithBytesNoCopy", 1, InvalidIdx, PossibleAPI},        // 7
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)unsigned MacOSKeychainAPIChecker::getTrackedFunctionIndex(StringRef Name,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                          bool IsAllocator) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned I = 0; I < FunctionsToTrackSize; ++I) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ADFunctionInfo FI = FunctionsToTrack[I];
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (FI.Name != Name)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure the function is of the right type (allocator vs deallocator).
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (IsAllocator && (FI.DeallocatorIdx == InvalidIdx))
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return InvalidIdx;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!IsAllocator && (FI.DeallocatorIdx != InvalidIdx))
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return InvalidIdx;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return I;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The function is not tracked.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return InvalidIdx;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static SymbolRef getSymbolForRegion(CheckerContext &C,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const MemRegion *R) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Implicit casts (ex: void* -> char*) can turn Symbolic region into element
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // region, if that is the case, get the underlining region.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  R = R->StripCasts();
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!isa<SymbolicRegion>(R)) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cast<SymbolicRegion>(R)->getSymbol();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool isBadDeallocationArgument(const MemRegion *Arg) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (isa<AllocaRegion>(Arg) ||
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      isa<BlockDataRegion>(Arg) ||
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      isa<TypedRegion>(Arg)) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// Given the address expression, retrieve the value it's pointing to. Assume
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// that value is itself an address, and return the corresponding symbol.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static SymbolRef getAsPointeeSymbol(const Expr *Expr,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    CheckerContext &C) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *State = C.getState();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SVal ArgV = State->getSVal(Expr);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StoreManager& SM = C.getStoreManager();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MemRegion *V = SM.Retrieve(State->getStore(), *X).getAsRegion();
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (V)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return getSymbolForRegion(C, V);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// When checking for error code, we need to consider the following cases:
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 1) noErr / [0]
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2) someErr / [1, inf]
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 3) unknown
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// If noError, returns true iff (1).
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// If !noError, returns true iff (2).
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                      const ProgramState *State,
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                      SValBuilder &Builder,
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                      bool noError) const {
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DefinedOrUnknownSVal NoErrVal = Builder.makeIntVal(NoErr,
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Builder.getSymbolManager().getType(RetSym));
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal,
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                     nonloc::SymbolVal(RetSym));
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ProgramState *ErrState = State->assume(NoErr, noError);
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ErrState == State) {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Report deallocator mismatch. Remove the region from tracking - reporting a
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// missing free error after this one is redundant.
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MacOSKeychainAPIChecker::
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  generateDeallocatorMismatchReport(const AllocationPair &AP,
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    const Expr *ArgExpr,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    CheckerContext &C) const {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *State = C.getState();
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  State = State->remove<AllocatedData>(AP.first);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExplodedNode *N = C.generateNode(State);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!N)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initBugType();
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  llvm::SmallString<80> sbuf;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::raw_svector_ostream os(sbuf);
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int PDeallocIdx =
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               FunctionsToTrack[AP.second->AllocatorIdx].DeallocatorIdx;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  os << "Deallocator doesn't match the allocator: '"
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     << FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BugReport *Report = new BugReport(*BT, os.str(), N);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Report->addVisitor(new SecKeychainBugVisitor(AP.first));
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Report->addRange(ArgExpr->getSourceRange());
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  C.EmitReport(Report);
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           CheckerContext &C) const {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *State = C.getState();
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Expr *Callee = CE->getCallee();
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SVal L = State->getSVal(Callee);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned idx = InvalidIdx;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FunctionDecl *funDecl = L.getAsFunctionDecl();
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!funDecl)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IdentifierInfo *funI = funDecl->getIdentifier();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!funI)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringRef funName = funI->getName();
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it is a call to an allocator function, it could be a double allocation.
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  idx = getTrackedFunctionIndex(funName, true);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idx != InvalidIdx) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C))
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (const AllocationState *AS = State->get<AllocatedData>(V)) {
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (!definitelyReturnedError(AS->Region, State, C.getSValBuilder())) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Remove the value from the state. The new symbol will be added for
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // tracking when the second allocator is processed in checkPostStmt().
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          State = State->remove<AllocatedData>(V);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ExplodedNode *N = C.generateNode(State);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (!N)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          initBugType();
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          llvm::SmallString<128> sbuf;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          llvm::raw_svector_ostream os(sbuf);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          unsigned int DIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          os << "Allocated data should be released before another call to "
3153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch              << "the allocator: missing a call to '"
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              << FunctionsToTrack[DIdx].Name
3173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch              << "'.";
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          BugReport *Report = new BugReport(*BT, os.str(), N);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          Report->addVisitor(new SecKeychainBugVisitor(V));
320bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch          Report->addRange(ArgExpr->getSourceRange());
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          C.EmitReport(Report);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Is it a call to one of deallocator functions?
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  idx = getTrackedFunctionIndex(funName, false);
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idx == InvalidIdx)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the argument to the deallocator.
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SVal ArgSVal = State->getSVal(ArgExpr);
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Undef is reported by another checker.
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ArgSVal.isUndef())
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const MemRegion *Arg = ArgSVal.getAsRegion();
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!Arg)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SymbolRef ArgSM = getSymbolForRegion(C, Arg);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool RegionArgIsBad = ArgSM ? false : isBadDeallocationArgument(Arg);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the argument is coming from the heap, globals, or unknown, do not
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // report it.
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!ArgSM && !RegionArgIsBad)
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Is the argument to the call being tracked?
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const AllocationState *AS = State->get<AllocatedData>(ArgSM);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!AS && FunctionsToTrack[idx].Kind != ValidAPI) {
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If trying to free data which has not been allocated yet, report as a bug.
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO: We might want a more precise diagnostic for double free
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (that would involve tracking all the freed symbols in the checker state).
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!AS || RegionArgIsBad) {
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // It is possible that this is a false positive - the argument might
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have entered as an enclosing function parameter.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (isEnclosingFunctionParam(ArgExpr))
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ExplodedNode *N = C.generateNode(State);
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!N)
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    initBugType();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BugReport *Report = new BugReport(*BT,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "Trying to free data which has not been allocated.", N);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Report->addRange(ArgExpr->getSourceRange());
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    C.EmitReport(Report);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Process functions which might deallocate.
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FunctionsToTrack[idx].Kind == PossibleAPI) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (funName == "CFStringCreateWithBytesNoCopy") {
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const Expr *DeallocatorExpr = CE->getArg(5)->IgnoreParenCasts();
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // NULL ~ default deallocator, so warn.
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (DeallocatorExpr->isNullPointerConstant(C.getASTContext(),
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          Expr::NPC_ValueDependentIsNotNull)) {
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const AllocationPair AP = std::make_pair(ArgSM, AS);
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        generateDeallocatorMismatchReport(AP, ArgExpr, C);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // One of the default allocators, so warn.
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(DeallocatorExpr)) {
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StringRef DeallocatorName = DE->getFoundDecl()->getName();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DeallocatorName == "kCFAllocatorDefault" ||
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DeallocatorName == "kCFAllocatorSystemDefault" ||
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DeallocatorName == "kCFAllocatorMalloc") {
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const AllocationPair AP = std::make_pair(ArgSM, AS);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          generateDeallocatorMismatchReport(AP, ArgExpr, C);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If kCFAllocatorNull, which does not deallocate, we still have to
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // find the deallocator. Otherwise, assume that the user had written a
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // custom deallocator which does the right thing.
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DE->getFoundDecl()->getName() != "kCFAllocatorNull") {
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          State = State->remove<AllocatedData>(ArgSM);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          C.addTransition(State);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The call is deallocating a value we previously allocated, so remove it
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from the next state.
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  State = State->remove<AllocatedData>(ArgSM);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if the proper deallocator is used.
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int PDeallocIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (PDeallocIdx != idx || (FunctionsToTrack[idx].Kind == ErrorAPI)) {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AllocationPair AP = std::make_pair(ArgSM, AS);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    generateDeallocatorMismatchReport(AP, ArgExpr, C);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the return status is undefined or is error, report a bad call to free.
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExplodedNode *N = C.generateNode(State);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!N)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    initBugType();
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BugReport *Report = new BugReport(*BT,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "Call to free data when error was returned during allocation.", N);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Report->addVisitor(new SecKeychainBugVisitor(ArgSM));
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Report->addRange(ArgExpr->getSourceRange());
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    C.EmitReport(Report);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  C.addTransition(State);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            CheckerContext &C) const {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *State = C.getState();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Expr *Callee = CE->getCallee();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SVal L = State->getSVal(Callee);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FunctionDecl *funDecl = L.getAsFunctionDecl();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!funDecl)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IdentifierInfo *funI = funDecl->getIdentifier();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!funI)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringRef funName = funI->getName();
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a value has been allocated, add it to the set for tracking.
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned idx = getTrackedFunctionIndex(funName, true);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idx == InvalidIdx)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the argument entered as an enclosing function parameter, skip it to
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // avoid false positives.
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (isEnclosingFunctionParam(ArgExpr))
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If the argument points to something that's not a symbolic region, it
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // can be:
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //  - unknown (cannot reason about it)
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //  - undefined (already reported by other checker)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //  - constant (null - should not be tracked,
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //              other constant will generate a compiler warning)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //  - goto (should be reported by other checker)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The call return value symbol should stay alive for as long as the
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // allocated value symbol, since our diagnostics depend on the value
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // returned by the call. Ex: Data should only be freed if noErr was
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // returned during allocation.)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SymbolRef RetStatusSymbol = State->getSVal(CE).getAsSymbol();
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Track the allocated value in the checker state.
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    State = State->set<AllocatedData>(V, AllocationState(ArgExpr, idx,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                         RetStatusSymbol));
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    assert(State);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    C.addTransition(State);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S,
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           CheckerContext &C) const {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Expr *retExpr = S->getRetValue();
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!retExpr)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check  if the value is escaping through the return.
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *state = C.getState();
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const MemRegion *V = state->getSVal(retExpr).getAsRegion();
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!V)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state = state->remove<AllocatedData>(getSymbolForRegion(C, V));
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Proceed from the new state.
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  C.addTransition(state);
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BugReport *MacOSKeychainAPIChecker::
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         ExplodedNode *N) const {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initBugType();
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::SmallString<70> sbuf;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::raw_svector_ostream os(sbuf);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  os << "Allocated data is not released: missing a call to '"
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << FunctionsToTrack[FI.DeallocatorIdx].Name << "'.";
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BugReport *Report = new BugReport(*BT, os.str(), N);
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Report->addVisitor(new SecKeychainBugVisitor(AP.first));
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Report->addRange(SourceRange());
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Report;
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               CheckerContext &C) const {
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ProgramState *State = C.getState();
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AllocatedSetTy ASet = State->get<AllocatedData>();
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ASet.isEmpty())
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Changed = false;
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AllocationPairVec Errors;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (AllocatedSetTy::iterator I = ASet.begin(), E = ASet.end(); I != E; ++I) {
532    if (SR.isLive(I->first))
533      continue;
534
535    Changed = true;
536    State = State->remove<AllocatedData>(I->first);
537    // If the allocated symbol is null or if the allocation call might have
538    // returned an error, do not report.
539    if (State->getSymVal(I->first) ||
540        definitelyReturnedError(I->second.Region, State, C.getSValBuilder()))
541      continue;
542    Errors.push_back(std::make_pair(I->first, &I->second));
543  }
544  if (!Changed)
545    return;
546
547  // Generate the new, cleaned up state.
548  ExplodedNode *N = C.generateNode(State);
549  if (!N)
550    return;
551
552  // Generate the error reports.
553  for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end();
554                                                       I != E; ++I) {
555    C.EmitReport(generateAllocatedDataNotReleasedReport(*I, N));
556  }
557}
558
559// TODO: Remove this after we ensure that checkDeadSymbols are always called.
560void MacOSKeychainAPIChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
561                                           ExprEngine &Eng) const {
562  const ProgramState *state = B.getState();
563  AllocatedSetTy AS = state->get<AllocatedData>();
564  if (AS.isEmpty())
565    return;
566
567  // Anything which has been allocated but not freed (nor escaped) will be
568  // found here, so report it.
569  bool Changed = false;
570  AllocationPairVec Errors;
571  for (AllocatedSetTy::iterator I = AS.begin(), E = AS.end(); I != E; ++I ) {
572    Changed = true;
573    state = state->remove<AllocatedData>(I->first);
574    // If the allocated symbol is null or if error code was returned at
575    // allocation, do not report.
576    if (state->getSymVal(I.getKey()) ||
577        definitelyReturnedError(I->second.Region, state,
578                                Eng.getSValBuilder())) {
579      continue;
580    }
581    Errors.push_back(std::make_pair(I->first, &I->second));
582  }
583
584  // If no change, do not generate a new state.
585  if (!Changed)
586    return;
587
588  ExplodedNode *N = B.generateNode(state);
589  if (!N)
590    return;
591
592  // Generate the error reports.
593  for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end();
594                                                       I != E; ++I) {
595    Eng.getBugReporter().EmitReport(
596      generateAllocatedDataNotReleasedReport(*I, N));
597  }
598}
599
600
601PathDiagnosticPiece *MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
602                                                      const ExplodedNode *N,
603                                                      const ExplodedNode *PrevN,
604                                                      BugReporterContext &BRC,
605                                                      BugReport &BR) {
606  const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
607  if (!AS)
608    return 0;
609  const AllocationState *ASPrev = PrevN->getState()->get<AllocatedData>(Sym);
610  if (ASPrev)
611    return 0;
612
613  // (!ASPrev && AS) ~ We started tracking symbol in node N, it must be the
614  // allocation site.
615  const CallExpr *CE = cast<CallExpr>(cast<StmtPoint>(N->getLocation())
616                                                            .getStmt());
617  const FunctionDecl *funDecl = CE->getDirectCallee();
618  assert(funDecl && "We do not support indirect function calls as of now.");
619  StringRef funName = funDecl->getName();
620
621  // Get the expression of the corresponding argument.
622  unsigned Idx = getTrackedFunctionIndex(funName, true);
623  assert(Idx != InvalidIdx && "This should be a call to an allocator.");
624  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[Idx].Param);
625  PathDiagnosticLocation Pos(ArgExpr, BRC.getSourceManager());
626  return new PathDiagnosticEventPiece(Pos, "Data is allocated here.");
627}
628
629void ento::registerMacOSKeychainAPIChecker(CheckerManager &mgr) {
630  mgr.registerChecker<MacOSKeychainAPIChecker>();
631}
632