//==--- MacOSKeychainAPIChecker.cpp ------------------------------*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This checker flags misuses of KeyChainAPI. In particular, the password data
// allocated/returned by SecKeychainItemCopyContent,
// SecKeychainFindGenericPassword, SecKeychainFindInternetPassword functions has
// to be freed using a call to SecKeychainItemFreeContent.
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>

using namespace clang;
using namespace ento;

namespace {
class MacOSKeychainAPIChecker : public Checker<check::PreStmt<CallExpr>,
                                               check::PostStmt<CallExpr>,
                                               check::DeadSymbols,
                                               check::PointerEscape,
                                               eval::Assume> {
  mutable std::unique_ptr<BugType> BT;

public:
  /// AllocationState is a part of the checker specific state together with the
  /// MemRegion corresponding to the allocated data.
  struct AllocationState {
    /// The index of the allocator function.
    unsigned int AllocatorIdx;
    SymbolRef Region;

    AllocationState(const Expr *E, unsigned int Idx, SymbolRef R) :
      AllocatorIdx(Idx),
      Region(R) {}

    bool operator==(const AllocationState &X) const {
      return (AllocatorIdx == X.AllocatorIdx &&
              Region == X.Region);
    }

    void Profile(llvm::FoldingSetNodeID &ID) const {
      ID.AddInteger(AllocatorIdx);
      ID.AddPointer(Region);
    }
  };

  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
  void checkPostStmt(const CallExpr *S, CheckerContext &C) const;
  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
  ProgramStateRef checkPointerEscape(ProgramStateRef State,
                                     const InvalidatedSymbols &Escaped,
                                     const CallEvent *Call,
                                     PointerEscapeKind Kind) const;
  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
                             bool Assumption) const;
  void printState(raw_ostream &Out, ProgramStateRef State,
                  const char *NL, const char *Sep) const override;

private:
  typedef std::pair<SymbolRef, const AllocationState*> AllocationPair;
  typedef SmallVector<AllocationPair, 2> AllocationPairVec;

  enum APIKind {
    /// Denotes functions tracked by this checker.
    ValidAPI = 0,
    /// The functions commonly/mistakenly used in place of the given API.
    ErrorAPI = 1,
    /// The functions which may allocate the data. These are tracked to reduce
    /// the false alarm rate.
    PossibleAPI = 2
  };
  /// Stores the information about the allocator and deallocator functions -
  /// these are the functions the checker is tracking.
  struct ADFunctionInfo {
    const char* Name;
    unsigned int Param;
    unsigned int DeallocatorIdx;
    APIKind Kind;
  };
  static const unsigned InvalidIdx = 100000;
  static const unsigned FunctionsToTrackSize = 8;
  static const ADFunctionInfo FunctionsToTrack[FunctionsToTrackSize];
  /// The value, which represents no error return value for allocator functions.
  static const unsigned NoErr = 0;

  /// Given the function name, returns the index of the allocator/deallocator
  /// function.
  static unsigned getTrackedFunctionIndex(StringRef Name, bool IsAllocator);

  inline void initBugType() const {
    if (!BT)
      BT.reset(new BugType(this, "Improper use of SecKeychain API",
                           "API Misuse (Apple)"));
  }

  void generateDeallocatorMismatchReport(const AllocationPair &AP,
                                         const Expr *ArgExpr,
                                         CheckerContext &C) const;

  /// Find the allocation site for Sym on the path leading to the node N.
  const ExplodedNode *getAllocationNode(const ExplodedNode *N, SymbolRef Sym,
                                        CheckerContext &C) const;

  std::unique_ptr<PathSensitiveBugReport>
  generateAllocatedDataNotReleasedReport(const AllocationPair &AP,
                                         ExplodedNode *N,
                                         CheckerContext &C) const;

  /// Mark an AllocationPair interesting for diagnostic reporting.
  void markInteresting(PathSensitiveBugReport *R,
                       const AllocationPair &AP) const {
    R->markInteresting(AP.first);
    R->markInteresting(AP.second->Region);
  }

  /// The bug visitor which allows us to print extra diagnostics along the
  /// BugReport path. For example, showing the allocation site of the leaked
  /// region.
  class SecKeychainBugVisitor : public BugReporterVisitor {
  protected:
    // The allocated region symbol tracked by the main analysis.
    SymbolRef Sym;

  public:
    SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}

    void Profile(llvm::FoldingSetNodeID &ID) const override {
      static int X = 0;
      ID.AddPointer(&X);
      ID.AddPointer(Sym);
    }

    PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                     BugReporterContext &BRC,
                                     PathSensitiveBugReport &BR) override;
  };
};
}

/// ProgramState traits to store the currently allocated (and not yet freed)
/// symbols. This is a map from the allocated content symbol to the
/// corresponding AllocationState.
REGISTER_MAP_WITH_PROGRAMSTATE(AllocatedData,
                               SymbolRef,
                               MacOSKeychainAPIChecker::AllocationState)

static bool isEnclosingFunctionParam(const Expr *E) {
  E = E->IgnoreParenCasts();
  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
    const ValueDecl *VD = DRE->getDecl();
    if (isa<ImplicitParamDecl, ParmVarDecl>(VD))
      return true;
  }
  return false;
}

const MacOSKeychainAPIChecker::ADFunctionInfo
  MacOSKeychainAPIChecker::FunctionsToTrack[FunctionsToTrackSize] = {
    {"SecKeychainItemCopyContent", 4, 3, ValidAPI},                       // 0
    {"SecKeychainFindGenericPassword", 6, 3, ValidAPI},                   // 1
    {"SecKeychainFindInternetPassword", 13, 3, ValidAPI},                 // 2
    {"SecKeychainItemFreeContent", 1, InvalidIdx, ValidAPI},              // 3
    {"SecKeychainItemCopyAttributesAndData", 5, 5, ValidAPI},             // 4
    {"SecKeychainItemFreeAttributesAndData", 1, InvalidIdx, ValidAPI},    // 5
    {"free", 0, InvalidIdx, ErrorAPI},                                    // 6
    {"CFStringCreateWithBytesNoCopy", 1, InvalidIdx, PossibleAPI},        // 7
};

unsigned MacOSKeychainAPIChecker::getTrackedFunctionIndex(StringRef Name,
                                                          bool IsAllocator) {
  for (unsigned I = 0; I < FunctionsToTrackSize; ++I) {
    ADFunctionInfo FI = FunctionsToTrack[I];
    if (FI.Name != Name)
      continue;
    // Make sure the function is of the right type (allocator vs deallocator).
    if (IsAllocator && (FI.DeallocatorIdx == InvalidIdx))
      return InvalidIdx;
    if (!IsAllocator && (FI.DeallocatorIdx != InvalidIdx))
      return InvalidIdx;

    return I;
  }
  // The function is not tracked.
  return InvalidIdx;
}

static bool isBadDeallocationArgument(const MemRegion *Arg) {
  if (!Arg)
    return false;
  return isa<AllocaRegion, BlockDataRegion, TypedRegion>(Arg);
}

/// Given the address expression, retrieve the value it's pointing to. Assume
/// that value is itself an address, and return the corresponding symbol.
static SymbolRef getAsPointeeSymbol(const Expr *Expr,
                                    CheckerContext &C) {
  ProgramStateRef State = C.getState();
  SVal ArgV = C.getSVal(Expr);

  if (std::optional<loc::MemRegionVal> X = ArgV.getAs<loc::MemRegionVal>()) {
    StoreManager& SM = C.getStoreManager();
    SymbolRef sym = SM.getBinding(State->getStore(), *X).getAsLocSymbol();
    if (sym)
      return sym;
  }
  return nullptr;
}

// Report deallocator mismatch. Remove the region from tracking - reporting a
// missing free error after this one is redundant.
void MacOSKeychainAPIChecker::
  generateDeallocatorMismatchReport(const AllocationPair &AP,
                                    const Expr *ArgExpr,
                                    CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  State = State->remove<AllocatedData>(AP.first);
  ExplodedNode *N = C.generateNonFatalErrorNode(State);

  if (!N)
    return;
  initBugType();
  SmallString<80> sbuf;
  llvm::raw_svector_ostream os(sbuf);
  unsigned int PDeallocIdx =
               FunctionsToTrack[AP.second->AllocatorIdx].DeallocatorIdx;

  os << "Deallocator doesn't match the allocator: '"
     << FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
  auto Report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
  Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
  Report->addRange(ArgExpr->getSourceRange());
  markInteresting(Report.get(), AP);
  C.emitReport(std::move(Report));
}

void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
                                           CheckerContext &C) const {
  unsigned idx = InvalidIdx;
  ProgramStateRef State = C.getState();

  const FunctionDecl *FD = C.getCalleeDecl(CE);
  if (!FD || FD->getKind() != Decl::Function)
    return;

  StringRef funName = C.getCalleeName(FD);
  if (funName.empty())
    return;

  // If it is a call to an allocator function, it could be a double allocation.
  idx = getTrackedFunctionIndex(funName, true);
  if (idx != InvalidIdx) {
    unsigned paramIdx = FunctionsToTrack[idx].Param;
    if (CE->getNumArgs() <= paramIdx)
      return;

    const Expr *ArgExpr = CE->getArg(paramIdx);
    if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C))
      if (const AllocationState *AS = State->get<AllocatedData>(V)) {
        // Remove the value from the state. The new symbol will be added for
        // tracking when the second allocator is processed in checkPostStmt().
        State = State->remove<AllocatedData>(V);
        ExplodedNode *N = C.generateNonFatalErrorNode(State);
        if (!N)
          return;
        initBugType();
        SmallString<128> sbuf;
        llvm::raw_svector_ostream os(sbuf);
        unsigned int DIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
        os << "Allocated data should be released before another call to "
            << "the allocator: missing a call to '"
            << FunctionsToTrack[DIdx].Name
            << "'.";
        auto Report =
            std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
        Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(V));
        Report->addRange(ArgExpr->getSourceRange());
        Report->markInteresting(AS->Region);
        C.emitReport(std::move(Report));
      }
    return;
  }

  // Is it a call to one of deallocator functions?
  idx = getTrackedFunctionIndex(funName, false);
  if (idx == InvalidIdx)
    return;

  unsigned paramIdx = FunctionsToTrack[idx].Param;
  if (CE->getNumArgs() <= paramIdx)
    return;

  // Check the argument to the deallocator.
  const Expr *ArgExpr = CE->getArg(paramIdx);
  SVal ArgSVal = C.getSVal(ArgExpr);

  // Undef is reported by another checker.
  if (ArgSVal.isUndef())
    return;

  SymbolRef ArgSM = ArgSVal.getAsLocSymbol();

  // If the argument is coming from the heap, globals, or unknown, do not
  // report it.
  bool RegionArgIsBad = false;
  if (!ArgSM) {
    if (!isBadDeallocationArgument(ArgSVal.getAsRegion()))
      return;
    RegionArgIsBad = true;
  }

  // Is the argument to the call being tracked?
  const AllocationState *AS = State->get<AllocatedData>(ArgSM);
  if (!AS)
    return;

  // TODO: We might want to report double free here.
  // (that would involve tracking all the freed symbols in the checker state).
  if (RegionArgIsBad) {
    // It is possible that this is a false positive - the argument might
    // have entered as an enclosing function parameter.
    if (isEnclosingFunctionParam(ArgExpr))
      return;

    ExplodedNode *N = C.generateNonFatalErrorNode(State);
    if (!N)
      return;
    initBugType();
    auto Report = std::make_unique<PathSensitiveBugReport>(
        *BT, "Trying to free data which has not been allocated.", N);
    Report->addRange(ArgExpr->getSourceRange());
    if (AS)
      Report->markInteresting(AS->Region);
    C.emitReport(std::move(Report));
    return;
  }

  // Process functions which might deallocate.
  if (FunctionsToTrack[idx].Kind == PossibleAPI) {

    if (funName == "CFStringCreateWithBytesNoCopy") {
      const Expr *DeallocatorExpr = CE->getArg(5)->IgnoreParenCasts();
      // NULL ~ default deallocator, so warn.
      if (DeallocatorExpr->isNullPointerConstant(C.getASTContext(),
          Expr::NPC_ValueDependentIsNotNull)) {
        const AllocationPair AP = std::make_pair(ArgSM, AS);
        generateDeallocatorMismatchReport(AP, ArgExpr, C);
        return;
      }
      // One of the default allocators, so warn.
      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(DeallocatorExpr)) {
        StringRef DeallocatorName = DE->getFoundDecl()->getName();
        if (DeallocatorName == "kCFAllocatorDefault" ||
            DeallocatorName == "kCFAllocatorSystemDefault" ||
            DeallocatorName == "kCFAllocatorMalloc") {
          const AllocationPair AP = std::make_pair(ArgSM, AS);
          generateDeallocatorMismatchReport(AP, ArgExpr, C);
          return;
        }
        // If kCFAllocatorNull, which does not deallocate, we still have to
        // find the deallocator.
        if (DE->getFoundDecl()->getName() == "kCFAllocatorNull")
          return;
      }
      // In all other cases, assume the user supplied a correct deallocator
      // that will free memory so stop tracking.
      State = State->remove<AllocatedData>(ArgSM);
      C.addTransition(State);
      return;
    }

    llvm_unreachable("We know of no other possible APIs.");
  }

  // The call is deallocating a value we previously allocated, so remove it
  // from the next state.
  State = State->remove<AllocatedData>(ArgSM);

  // Check if the proper deallocator is used.
  unsigned int PDeallocIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
  if (PDeallocIdx != idx || (FunctionsToTrack[idx].Kind == ErrorAPI)) {
    const AllocationPair AP = std::make_pair(ArgSM, AS);
    generateDeallocatorMismatchReport(AP, ArgExpr, C);
    return;
  }

  C.addTransition(State);
}

void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
                                            CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  const FunctionDecl *FD = C.getCalleeDecl(CE);
  if (!FD || FD->getKind() != Decl::Function)
    return;

  StringRef funName = C.getCalleeName(FD);

  // If a value has been allocated, add it to the set for tracking.
  unsigned idx = getTrackedFunctionIndex(funName, true);
  if (idx == InvalidIdx)
    return;

  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
  // If the argument entered as an enclosing function parameter, skip it to
  // avoid false positives.
  if (isEnclosingFunctionParam(ArgExpr) &&
      C.getLocationContext()->getParent() == nullptr)
    return;

  if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
    // If the argument points to something that's not a symbolic region, it
    // can be:
    //  - unknown (cannot reason about it)
    //  - undefined (already reported by other checker)
    //  - constant (null - should not be tracked,
    //              other constant will generate a compiler warning)
    //  - goto (should be reported by other checker)

    // The call return value symbol should stay alive for as long as the
    // allocated value symbol, since our diagnostics depend on the value
    // returned by the call. Ex: Data should only be freed if noErr was
    // returned during allocation.)
    SymbolRef RetStatusSymbol = C.getSVal(CE).getAsSymbol();
    C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);

    // Track the allocated value in the checker state.
    State = State->set<AllocatedData>(V, AllocationState(ArgExpr, idx,
                                                         RetStatusSymbol));
    assert(State);
    C.addTransition(State);
  }
}

// TODO: This logic is the same as in Malloc checker.
const ExplodedNode *
MacOSKeychainAPIChecker::getAllocationNode(const ExplodedNode *N,
                                           SymbolRef Sym,
                                           CheckerContext &C) const {
  const LocationContext *LeakContext = N->getLocationContext();
  // Walk the ExplodedGraph backwards and find the first node that referred to
  // the tracked symbol.
  const ExplodedNode *AllocNode = N;

  while (N) {
    if (!N->getState()->get<AllocatedData>(Sym))
      break;
    // Allocation node, is the last node in the current or parent context in
    // which the symbol was tracked.
    const LocationContext *NContext = N->getLocationContext();
    if (NContext == LeakContext ||
        NContext->isParentOf(LeakContext))
      AllocNode = N;
    N = N->pred_empty() ? nullptr : *(N->pred_begin());
  }

  return AllocNode;
}

std::unique_ptr<PathSensitiveBugReport>
MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
    const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const {
  const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
  initBugType();
  SmallString<70> sbuf;
  llvm::raw_svector_ostream os(sbuf);
  os << "Allocated data is not released: missing a call to '"
      << FunctionsToTrack[FI.DeallocatorIdx].Name << "'.";

  // Most bug reports are cached at the location where they occurred.
  // With leaks, we want to unique them by the location where they were
  // allocated, and only report a single path.
  PathDiagnosticLocation LocUsedForUniqueing;
  const ExplodedNode *AllocNode = getAllocationNode(N, AP.first, C);
  const Stmt *AllocStmt = AllocNode->getStmtForDiagnostics();

  if (AllocStmt)
    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
                                              C.getSourceManager(),
                                              AllocNode->getLocationContext());

  auto Report = std::make_unique<PathSensitiveBugReport>(
      *BT, os.str(), N, LocUsedForUniqueing,
      AllocNode->getLocationContext()->getDecl());

  Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
  markInteresting(Report.get(), AP);
  return Report;
}

/// If the return symbol is assumed to be error, remove the allocated info
/// from consideration.
ProgramStateRef MacOSKeychainAPIChecker::evalAssume(ProgramStateRef State,
                                                    SVal Cond,
                                                    bool Assumption) const {
  AllocatedDataTy AMap = State->get<AllocatedData>();
  if (AMap.isEmpty())
    return State;

  auto *CondBSE = dyn_cast_or_null<BinarySymExpr>(Cond.getAsSymbol());
  if (!CondBSE)
    return State;
  BinaryOperator::Opcode OpCode = CondBSE->getOpcode();
  if (OpCode != BO_EQ && OpCode != BO_NE)
    return State;

  // Match for a restricted set of patterns for cmparison of error codes.
  // Note, the comparisons of type '0 == st' are transformed into SymIntExpr.
  SymbolRef ReturnSymbol = nullptr;
  if (auto *SIE = dyn_cast<SymIntExpr>(CondBSE)) {
    const llvm::APInt &RHS = SIE->getRHS();
    bool ErrorIsReturned = (OpCode == BO_EQ && RHS != NoErr) ||
                           (OpCode == BO_NE && RHS == NoErr);
    if (!Assumption)
      ErrorIsReturned = !ErrorIsReturned;
    if (ErrorIsReturned)
      ReturnSymbol = SIE->getLHS();
  }

  if (ReturnSymbol)
    for (auto I = AMap.begin(), E = AMap.end(); I != E; ++I) {
      if (ReturnSymbol == I->second.Region)
        State = State->remove<AllocatedData>(I->first);
    }

  return State;
}

void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
                                               CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  AllocatedDataTy AMap = State->get<AllocatedData>();
  if (AMap.isEmpty())
    return;

  bool Changed = false;
  AllocationPairVec Errors;
  for (auto I = AMap.begin(), E = AMap.end(); I != E; ++I) {
    if (!SR.isDead(I->first))
      continue;

    Changed = true;
    State = State->remove<AllocatedData>(I->first);
    // If the allocated symbol is null do not report.
    ConstraintManager &CMgr = State->getConstraintManager();
    ConditionTruthVal AllocFailed = CMgr.isNull(State, I.getKey());
    if (AllocFailed.isConstrainedTrue())
      continue;
    Errors.push_back(std::make_pair(I->first, &I->second));
  }
  if (!Changed) {
    // Generate the new, cleaned up state.
    C.addTransition(State);
    return;
  }

  static CheckerProgramPointTag Tag(this, "DeadSymbolsLeak");
  ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag);
  if (!N)
    return;

  // Generate the error reports.
  for (const auto &P : Errors)
    C.emitReport(generateAllocatedDataNotReleasedReport(P, N, C));

  // Generate the new, cleaned up state.
  C.addTransition(State, N);
}

ProgramStateRef MacOSKeychainAPIChecker::checkPointerEscape(
    ProgramStateRef State, const InvalidatedSymbols &Escaped,
    const CallEvent *Call, PointerEscapeKind Kind) const {
  // FIXME: This branch doesn't make any sense at all, but it is an overfitted
  // replacement for a previous overfitted code that was making even less sense.
  if (!Call || Call->getDecl())
    return State;

  for (auto I : State->get<AllocatedData>()) {
    SymbolRef Sym = I.first;
    if (Escaped.count(Sym))
      State = State->remove<AllocatedData>(Sym);

    // This checker is special. Most checkers in fact only track symbols of
    // SymbolConjured type, eg. symbols returned from functions such as
    // malloc(). This checker tracks symbols returned as out-parameters.
    //
    // When a function is evaluated conservatively, the out-parameter's pointee
    // base region gets invalidated with a SymbolConjured. If the base region is
    // larger than the region we're interested in, the value we're interested in
    // would be SymbolDerived based on that SymbolConjured. However, such
    // SymbolDerived will never be listed in the Escaped set when the base
    // region is invalidated because ExprEngine doesn't know which symbols
    // were derived from a given symbol, while there can be infinitely many
    // valid symbols derived from any given symbol.
    //
    // Hence the extra boilerplate: remove the derived symbol when its parent
    // symbol escapes.
    //
    if (const auto *SD = dyn_cast<SymbolDerived>(Sym)) {
      SymbolRef ParentSym = SD->getParentSymbol();
      if (Escaped.count(ParentSym))
        State = State->remove<AllocatedData>(Sym);
    }
  }
  return State;
}

PathDiagnosticPieceRef
MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
    const ExplodedNode *N, BugReporterContext &BRC,
    PathSensitiveBugReport &BR) {
  const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
  if (!AS)
    return nullptr;
  const AllocationState *ASPrev =
      N->getFirstPred()->getState()->get<AllocatedData>(Sym);
  if (ASPrev)
    return nullptr;

  // (!ASPrev && AS) ~ We started tracking symbol in node N, it must be the
  // allocation site.
  const CallExpr *CE =
      cast<CallExpr>(N->getLocation().castAs<StmtPoint>().getStmt());
  const FunctionDecl *funDecl = CE->getDirectCallee();
  assert(funDecl && "We do not support indirect function calls as of now.");
  StringRef funName = funDecl->getName();

  // Get the expression of the corresponding argument.
  unsigned Idx = getTrackedFunctionIndex(funName, true);
  assert(Idx != InvalidIdx && "This should be a call to an allocator.");
  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[Idx].Param);
  PathDiagnosticLocation Pos(ArgExpr, BRC.getSourceManager(),
                             N->getLocationContext());
  return std::make_shared<PathDiagnosticEventPiece>(Pos,
                                                    "Data is allocated here.");
}

void MacOSKeychainAPIChecker::printState(raw_ostream &Out,
                                         ProgramStateRef State,
                                         const char *NL,
                                         const char *Sep) const {

  AllocatedDataTy AMap = State->get<AllocatedData>();

  if (!AMap.isEmpty()) {
    Out << Sep << "KeychainAPIChecker :" << NL;
    for (auto I = AMap.begin(), E = AMap.end(); I != E; ++I) {
      I.getKey()->dumpToStream(Out);
    }
  }
}


void ento::registerMacOSKeychainAPIChecker(CheckerManager &mgr) {
  mgr.registerChecker<MacOSKeychainAPIChecker>();
}

bool ento::shouldRegisterMacOSKeychainAPIChecker(const CheckerManager &mgr) {
  return true;
}
