//== ObjCContainersChecker.cpp - Path sensitive checker for CFArray *- C++ -*=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Performs path sensitive checks of Core Foundation static containers like
// CFArray.
// 1) Check for buffer overflows:
//      In CFArrayGetArrayAtIndex( myArray, index), if the index is outside the
//      index space of theArray (0 to N-1 inclusive (where N is the count of
//      theArray), the behavior is undefined.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/ParentMap.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/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"

using namespace clang;
using namespace ento;

namespace {
class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>,
                                             check::PostStmt<CallExpr>,
                                             check::PointerEscape> {
  mutable std::unique_ptr<BugType> BT;
  inline void initBugType() const {
    if (!BT)
      BT.reset(new BugType(this, "CFArray API",
                           categories::CoreFoundationObjectiveC));
  }

  inline SymbolRef getArraySym(const Expr *E, CheckerContext &C) const {
    SVal ArrayRef = C.getState()->getSVal(E, C.getLocationContext());
    SymbolRef ArraySym = ArrayRef.getAsSymbol();
    return ArraySym;
  }

  void addSizeInfo(const Expr *Array, const Expr *Size,
                   CheckerContext &C) const;

public:
  /// A tag to id this checker.
  static void *getTag() { static int Tag; return &Tag; }

  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
  ProgramStateRef checkPointerEscape(ProgramStateRef State,
                                     const InvalidatedSymbols &Escaped,
                                     const CallEvent *Call,
                                     PointerEscapeKind Kind) const;
};
} // end anonymous namespace

// ProgramState trait - a map from array symbol to its state.
REGISTER_MAP_WITH_PROGRAMSTATE(ArraySizeMap, SymbolRef, DefinedSVal)

void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
                                        CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  SVal SizeV = State->getSVal(Size, C.getLocationContext());
  // Undefined is reported by another checker.
  if (SizeV.isUnknownOrUndef())
    return;

  // Get the ArrayRef symbol.
  SVal ArrayRef = State->getSVal(Array, C.getLocationContext());
  SymbolRef ArraySym = ArrayRef.getAsSymbol();
  if (!ArraySym)
    return;

  C.addTransition(
      State->set<ArraySizeMap>(ArraySym, SizeV.castAs<DefinedSVal>()));
  return;
}

void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
                                          CheckerContext &C) const {
  StringRef Name = C.getCalleeName(CE);
  if (Name.empty() || CE->getNumArgs() < 1)
    return;

  // Add array size information to the state.
  if (Name.equals("CFArrayCreate")) {
    if (CE->getNumArgs() < 3)
      return;
    // Note, we can visit the Create method in the post-visit because
    // the CFIndex parameter is passed in by value and will not be invalidated
    // by the call.
    addSizeInfo(CE, CE->getArg(2), C);
    return;
  }

  if (Name.equals("CFArrayGetCount")) {
    addSizeInfo(CE->getArg(0), CE, C);
    return;
  }
}

void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
                                         CheckerContext &C) const {
  StringRef Name = C.getCalleeName(CE);
  if (Name.empty() || CE->getNumArgs() < 2)
    return;

  // Check the array access.
  if (Name.equals("CFArrayGetValueAtIndex")) {
    ProgramStateRef State = C.getState();
    // Retrieve the size.
    // Find out if we saw this array symbol before and have information about
    // it.
    const Expr *ArrayExpr = CE->getArg(0);
    SymbolRef ArraySym = getArraySym(ArrayExpr, C);
    if (!ArraySym)
      return;

    const DefinedSVal *Size = State->get<ArraySizeMap>(ArraySym);

    if (!Size)
      return;

    // Get the index.
    const Expr *IdxExpr = CE->getArg(1);
    SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
    if (IdxVal.isUnknownOrUndef())
      return;
    DefinedSVal Idx = IdxVal.castAs<DefinedSVal>();

    // Now, check if 'Idx in [0, Size-1]'.
    const QualType T = IdxExpr->getType();
    ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
    ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
    if (StOutBound && !StInBound) {
      ExplodedNode *N = C.generateErrorNode(StOutBound);
      if (!N)
        return;
      initBugType();
      auto R = llvm::make_unique<BugReport>(*BT, "Index is out of bounds", N);
      R->addRange(IdxExpr->getSourceRange());
      C.emitReport(std::move(R));
      return;
    }
  }
}

ProgramStateRef
ObjCContainersChecker::checkPointerEscape(ProgramStateRef State,
                                          const InvalidatedSymbols &Escaped,
                                          const CallEvent *Call,
                                          PointerEscapeKind Kind) const {
  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
                                          E = Escaped.end();
                                          I != E; ++I) {
    SymbolRef Sym = *I;
    // When a symbol for a mutable array escapes, we can't reason precisely
    // about its size any more -- so remove it from the map.
    // Note that we aren't notified here when a CFMutableArrayRef escapes as a
    // CFArrayRef. This is because CFArrayRef is typedef'd as a pointer to a
    // const-qualified type.
    State = State->remove<ArraySizeMap>(Sym);
  }
  return State;
}
/// Register checker.
void ento::registerObjCContainersChecker(CheckerManager &mgr) {
  mgr.registerChecker<ObjCContainersChecker>();
}
