//=== IteratorsChecker.cpp - Check for Invalidated Iterators ------*- C++ -*----
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines IteratorsChecker, a number of small checks for conditions
// leading to invalid iterators being used.
// FIXME: Currently only supports 'vector' and 'deque'
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSwitch.h"


using namespace clang;
using namespace ento;

// This is the state associated with each iterator which includes both the
// kind of state and the instance used to initialize it.
// FIXME: add location where invalidated for better error reporting.
namespace {
class RefState {
  enum Kind { BeginValid, EndValid, Invalid, Undefined, Unknown } K;
  const void *VR;

public:
  RefState(Kind k, const void *vr) : K(k), VR(vr) {}

  bool isValid() const { return K == BeginValid || K == EndValid; }
  bool isInvalid() const { return K == Invalid; }
  bool isUndefined() const { return K == Undefined; }
  bool isUnknown() const { return K == Unknown; }
  const MemRegion *getMemRegion() const {
    if (K == BeginValid || K == EndValid)
      return(const MemRegion *)VR;
    return 0;
  }
  const MemberExpr *getMemberExpr() const {
    if (K == Invalid)
      return(const MemberExpr *)VR;
    return 0;
  }

  bool operator==(const RefState &X) const {
    return K == X.K && VR == X.VR;
  }

  static RefState getBeginValid(const MemRegion *vr) {
    assert(vr);
    return RefState(BeginValid, vr);
  }
  static RefState getEndValid(const MemRegion *vr) {
    assert(vr);
    return RefState(EndValid, vr);
  }
  static RefState getInvalid( const MemberExpr *ME ) {
    return RefState(Invalid, ME);
  }
  static RefState getUndefined( void ) {
    return RefState(Undefined, 0);
  }
  static RefState getUnknown( void ) {
    return RefState(Unknown, 0);
  }

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

enum RefKind { NoKind, VectorKind, VectorIteratorKind };

class IteratorsChecker : 
    public Checker<check::PreStmt<CXXOperatorCallExpr>,
                   check::PreStmt<DeclStmt>,
                   check::PreStmt<CXXMemberCallExpr>,
                   check::PreStmt<CallExpr> >
  {
  // Used when parsing iterators and vectors and deques.
  BuiltinBug *BT_Invalid, *BT_Undefined, *BT_Incompatible;

public:
  IteratorsChecker() :
    BT_Invalid(0), BT_Undefined(0), BT_Incompatible(0)
  {}
  static void *getTag() { static int tag; return &tag; }
    
  // Checker entry points.
  void checkPreStmt(const CXXOperatorCallExpr *OCE,
                    CheckerContext &C) const;

  void checkPreStmt(const DeclStmt *DS,
                    CheckerContext &C) const;

  void checkPreStmt(const CXXMemberCallExpr *MCE,
                    CheckerContext &C) const;

  void checkPreStmt(const CallExpr *CE,
                    CheckerContext &C) const;

private:
  const ProgramState *handleAssign(const ProgramState *state,
                                   const Expr *lexp,
                                   const Expr *rexp,
                                   const LocationContext *LC) const;

  const ProgramState *handleAssign(const ProgramState *state,
                                   const MemRegion *MR,
                                   const Expr *rexp,
                                   const LocationContext *LC) const;

  const ProgramState *invalidateIterators(const ProgramState *state,
                                          const MemRegion *MR,
                                          const MemberExpr *ME) const;

  void checkExpr(CheckerContext &C, const Expr *E) const;

  void checkArgs(CheckerContext &C, const CallExpr *CE) const;

  const MemRegion *getRegion(const ProgramState *state,
                             const Expr *E,
                             const LocationContext *LC) const;

  const DeclRefExpr *getDeclRefExpr(const Expr *E) const;
};

class IteratorState {
public:
  typedef llvm::ImmutableMap<const MemRegion *, RefState> EntryMap;
};
} //end anonymous namespace

namespace clang {
  namespace ento {
    template <>
    struct ProgramStateTrait<IteratorState> 
      : public ProgramStatePartialTrait<IteratorState::EntryMap> {
      static void *GDMIndex() { return IteratorsChecker::getTag(); }
    };
  }
}

void ento::registerIteratorsChecker(CheckerManager &mgr) {
  mgr.registerChecker<IteratorsChecker>();
}

// ===============================================
// Utility functions used by visitor functions
// ===============================================

// check a templated type for std::vector or std::deque
static RefKind getTemplateKind(const NamedDecl *td) {
  const DeclContext *dc = td->getDeclContext();
  const NamespaceDecl *nameSpace = dyn_cast<NamespaceDecl>(dc);
  if (!nameSpace || !isa<TranslationUnitDecl>(nameSpace->getDeclContext())
      || nameSpace->getName() != "std")
    return NoKind;
  
  StringRef name = td->getName();
  return llvm::StringSwitch<RefKind>(name)
    .Cases("vector", "deque", VectorKind)
    .Default(NoKind);
}

static RefKind getTemplateKind(const DeclContext *dc) {
  if (const ClassTemplateSpecializationDecl *td =
      dyn_cast<ClassTemplateSpecializationDecl>(dc))
    return getTemplateKind(cast<NamedDecl>(td));
  return NoKind;
}

static RefKind getTemplateKind(const TypedefType *tdt) {
  const TypedefNameDecl *td = tdt->getDecl();
  RefKind parentKind = getTemplateKind(td->getDeclContext());
  if (parentKind == VectorKind) {
    return llvm::StringSwitch<RefKind>(td->getName())
    .Cases("iterator",
           "const_iterator",
           "reverse_iterator", VectorIteratorKind)
    .Default(NoKind);
  }
  return NoKind;
}

static RefKind getTemplateKind(const TemplateSpecializationType *tsp) {
  const TemplateName &tname = tsp->getTemplateName();
  TemplateDecl *td = tname.getAsTemplateDecl();
  if (!td)
    return NoKind;
  return getTemplateKind(td);
}

static RefKind getTemplateKind(QualType T) {
  if (const TemplateSpecializationType *tsp = 
      T->getAs<TemplateSpecializationType>()) {
    return getTemplateKind(tsp);      
  }
  if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
    QualType namedType = ET->getNamedType();
    if (const TypedefType *tdt = namedType->getAs<TypedefType>()) 
      return getTemplateKind(tdt);
    if (const TemplateSpecializationType *tsp = 
        namedType->getAs<TemplateSpecializationType>()) {
      return getTemplateKind(tsp);      
    }
  }
  return NoKind;  
}

// Iterate through our map and invalidate any iterators that were
// initialized fromt the specified instance MemRegion.
const ProgramState *IteratorsChecker::invalidateIterators(const ProgramState *state,
                          const MemRegion *MR, const MemberExpr *ME) const {
  IteratorState::EntryMap Map = state->get<IteratorState>();
  if (Map.isEmpty())
    return state;

  // Loop over the entries in the current state.
  // The key doesn't change, so the map iterators won't change.
  for (IteratorState::EntryMap::iterator I = Map.begin(), E = Map.end();
                                                            I != E; ++I) {
    RefState RS = I.getData();
    if (RS.getMemRegion() == MR)
      state = state->set<IteratorState>(I.getKey(), RefState::getInvalid(ME));
  }

  return state;
}

// Handle assigning to an iterator where we don't have the LValue MemRegion.
const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
    const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
  // Skip the cast if present.
  if (const MaterializeTemporaryExpr *M 
                                    = dyn_cast<MaterializeTemporaryExpr>(lexp))
    lexp = M->GetTemporaryExpr();
  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
    lexp = ICE->getSubExpr();
  SVal sv = state->getSVal(lexp);
  const MemRegion *MR = sv.getAsRegion();
  if (!MR)
    return state;
  RefKind kind = getTemplateKind(lexp->getType());

  // If assigning to a vector, invalidate any iterators currently associated.
  if (kind == VectorKind)
    return invalidateIterators(state, MR, 0);

  // Make sure that we are assigning to an iterator.
  if (getTemplateKind(lexp->getType()) != VectorIteratorKind)
    return state;
  return handleAssign(state, MR, rexp, LC);
}

// handle assigning to an iterator
const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
    const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
  // Assume unknown until we find something definite.
  state = state->set<IteratorState>(MR, RefState::getUnknown());
  if (const MaterializeTemporaryExpr *M 
                                    = dyn_cast<MaterializeTemporaryExpr>(rexp))
    rexp = M->GetTemporaryExpr();
  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(rexp))
    rexp = ICE->getSubExpr();
  // Need to handle three cases: MemberCall, copy, copy with addition.
  if (const CallExpr *CE = dyn_cast<CallExpr>(rexp)) {
    // Handle MemberCall.
    if (const MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
      const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
      if (!DRE)
        return state;
      // Verify that the type is std::vector<T>.
      if (getTemplateKind(DRE->getType()) != VectorKind)
          return state;
      // Now get the MemRegion associated with the instance.
      const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
      if (!VD)
        return state;
      const MemRegion *IMR = state->getRegion(VD, LC);
      if (!IMR)
        return state;
      // Finally, see if it is one of the calls that will create
      // a valid iterator and mark it if so, else mark as Unknown.
      StringRef mName = ME->getMemberDecl()->getName();
      
      if (llvm::StringSwitch<bool>(mName)        
          .Cases("begin", "insert", "erase", true).Default(false)) {
        return state->set<IteratorState>(MR, RefState::getBeginValid(IMR));
      }
      if (mName == "end")
        return state->set<IteratorState>(MR, RefState::getEndValid(IMR));

      return state->set<IteratorState>(MR, RefState::getUnknown());
    }
  }
  // Handle straight copy from another iterator.
  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(rexp)) {
    if (getTemplateKind(DRE->getType()) != VectorIteratorKind)
      return state;
    // Now get the MemRegion associated with the instance.
    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
    if (!VD)
      return state;
    const MemRegion *IMR = state->getRegion(VD, LC);
    if (!IMR)
      return state;
    // Get the RefState of the iterator being copied.
    const RefState *RS = state->get<IteratorState>(IMR);
    if (!RS)
      return state;
    // Use it to set the state of the LValue.
    return state->set<IteratorState>(MR, *RS);
  }
  // If we have operator+ or operator- ...
  if (const CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(rexp)) {
    OverloadedOperatorKind Kind = OCE->getOperator();
    if (Kind == OO_Plus || Kind == OO_Minus) {
      // Check left side of tree for a valid value.
      state = handleAssign( state, MR, OCE->getArg(0), LC);
      const RefState *RS = state->get<IteratorState>(MR);
      // If found, return it.
      if (!RS->isUnknown())
        return state;
      // Otherwise return what we find in the right side.
      return handleAssign(state, MR, OCE->getArg(1), LC);
    }
  }
  // Fall through if nothing matched.
  return state;
}

// Iterate through the arguments looking for an Invalid or Undefined iterator.
void IteratorsChecker::checkArgs(CheckerContext &C, const CallExpr *CE) const {
  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
       I != E; ++I) {
    checkExpr(C, *I);
  }
}

// Get the DeclRefExpr associated with the expression.
const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
  // If it is a CXXConstructExpr, need to get the subexpression.
  if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
    if (CE->getNumArgs()== 1) {
      CXXConstructorDecl *CD = CE->getConstructor();
      if (CD->isTrivial())
        E = CE->getArg(0);
    }
  }
  if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
    E = M->GetTemporaryExpr();
  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
    E = ICE->getSubExpr();
  // If it isn't one of our types, don't do anything.
  if (getTemplateKind(E->getType()) != VectorIteratorKind)
    return NULL;
  return dyn_cast<DeclRefExpr>(E);
}

// Get the MemRegion associated with the expresssion.
const MemRegion *IteratorsChecker::getRegion(const ProgramState *state,
    const Expr *E, const LocationContext *LC) const {
  const DeclRefExpr *DRE = getDeclRefExpr(E);
  if (!DRE)
    return NULL;
  const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
  if (!VD)
    return NULL;
  // return the MemRegion associated with the iterator
  return state->getRegion(VD, LC);
}

// Check the expression and if it is an iterator, generate a diagnostic
// if the iterator is not valid.
// FIXME: this method can generate new nodes, and subsequent logic should
// use those nodes.  We also cannot create multiple nodes at one ProgramPoint
// with the same tag.
void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const {
  const ProgramState *state = C.getState();
  const MemRegion *MR = getRegion(state, E, C.getLocationContext());
  if (!MR)
    return;

  // Get the state associated with the iterator.
  const RefState *RS = state->get<IteratorState>(MR);
  if (!RS)
    return;
  if (RS->isInvalid()) {
    if (ExplodedNode *N = C.addTransition()) {
      if (!BT_Invalid)
        // FIXME: We are eluding constness here.
        const_cast<IteratorsChecker*>(this)->BT_Invalid = new BuiltinBug("");

      std::string msg;
      const MemberExpr *ME = RS->getMemberExpr();
      if (ME) {
        std::string name = ME->getMemberNameInfo().getAsString();
        msg = "Attempt to use an iterator made invalid by call to '" +
                                                                  name + "'";
      }
      else {
        msg = "Attempt to use an iterator made invalid by copying another "
                    "container to its container";
      }

      BugReport *R = new BugReport(*BT_Invalid, msg, N);
      R->addRange(getDeclRefExpr(E)->getSourceRange());
      C.EmitReport(R);
    }
  }
  else if (RS->isUndefined()) {
    if (ExplodedNode *N = C.addTransition()) {
      if (!BT_Undefined)
        // FIXME: We are eluding constness here.
        const_cast<IteratorsChecker*>(this)->BT_Undefined =
          new BuiltinBug("Use of iterator that is not defined");

      BugReport *R = new BugReport(*BT_Undefined,
                                           BT_Undefined->getDescription(), N);
      R->addRange(getDeclRefExpr(E)->getSourceRange());
      C.EmitReport(R);
    }
  }
}

// ===============================================
// Path analysis visitor functions
// ===============================================

// For a generic Call, just check the args for bad iterators.
void IteratorsChecker::checkPreStmt(const CallExpr *CE,
                                    CheckerContext &C) const{
  
  // FIXME: These checks are to currently work around a bug
  // in CheckerManager.
  if (isa<CXXOperatorCallExpr>(CE))
    return;
  if (isa<CXXMemberCallExpr>(CE))
    return;

  checkArgs(C, CE);
}

// Handle operator calls. First, if it is operator=, check the argument,
// and handle assigning and set target state appropriately. Otherwise, for
// other operators, check the args for bad iterators and handle comparisons.
void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
                                    CheckerContext &C) const
{
  const LocationContext *LC = C.getLocationContext();
  const ProgramState *state = C.getState();
  OverloadedOperatorKind Kind = OCE->getOperator();
  if (Kind == OO_Equal) {
    checkExpr(C, OCE->getArg(1));
    state = handleAssign(state, OCE->getArg(0), OCE->getArg(1), LC);
    C.addTransition(state);
    return;
  }
  else {
    checkArgs(C, OCE);
    // If it is a compare and both are iterators, ensure that they are for
    // the same container.
    if (Kind == OO_EqualEqual || Kind == OO_ExclaimEqual ||
        Kind == OO_Less || Kind == OO_LessEqual ||
        Kind == OO_Greater || Kind == OO_GreaterEqual) {
      const MemRegion *MR0, *MR1;
      MR0 = getRegion(state, OCE->getArg(0), LC);
      if (!MR0)
        return;
      MR1 = getRegion(state, OCE->getArg(1), LC);
      if (!MR1)
        return;
      const RefState *RS0, *RS1;
      RS0 = state->get<IteratorState>(MR0);
      if (!RS0)
        return;
      RS1 = state->get<IteratorState>(MR1);
      if (!RS1)
        return;
      if (RS0->getMemRegion() != RS1->getMemRegion()) {
      if (ExplodedNode *N = C.addTransition()) {
          if (!BT_Incompatible)
            const_cast<IteratorsChecker*>(this)->BT_Incompatible =
              new BuiltinBug(
                      "Cannot compare iterators from different containers");

          BugReport *R = new BugReport(*BT_Incompatible,
                                        BT_Incompatible->getDescription(), N);
          R->addRange(OCE->getSourceRange());
          C.EmitReport(R);
        }
      }
    }
  }
}

// Need to handle DeclStmts to pick up initializing of iterators and to mark
// uninitialized ones as Undefined.
void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
                                    CheckerContext &C) const {
  const Decl *D = *DS->decl_begin();
  const VarDecl *VD = dyn_cast<VarDecl>(D);
  // Only care about iterators.
  if (getTemplateKind(VD->getType()) != VectorIteratorKind)
    return;

  // Get the MemRegion associated with the iterator and mark it as Undefined.
  const ProgramState *state = C.getState();
  Loc VarLoc = state->getLValue(VD, C.getLocationContext());
  const MemRegion *MR = VarLoc.getAsRegion();
  if (!MR)
    return;
  state = state->set<IteratorState>(MR, RefState::getUndefined());

  // if there is an initializer, handle marking Valid if a proper initializer
  const Expr *InitEx = VD->getInit();
  if (InitEx) {
    // FIXME: This is too syntactic.  Since 'InitEx' will be analyzed first
    // it should resolve to an SVal that we can check for validity
    // *semantically* instead of walking through the AST.
    if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) {
      if (CE->getNumArgs() == 1) {
        const Expr *E = CE->getArg(0);
        if (const MaterializeTemporaryExpr *M
                                        = dyn_cast<MaterializeTemporaryExpr>(E))
          E = M->GetTemporaryExpr();
        if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
          InitEx = ICE->getSubExpr();
        state = handleAssign(state, MR, InitEx, C.getLocationContext());
      }
    }
  }
  C.addTransition(state);
}


namespace { struct CalledReserved {}; }
namespace clang { namespace ento {
template<> struct ProgramStateTrait<CalledReserved> 
    :  public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
  static void *GDMIndex() { static int index = 0; return &index; }
};
}}

// on a member call, first check the args for any bad iterators
// then, check to see if it is a call to a function that will invalidate
// the iterators
void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
                                    CheckerContext &C) const {
  // Check the arguments.
  checkArgs(C, MCE);
  const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee());
  if (!ME)
    return;
  // Make sure we have the right kind of container.
  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
  if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
    return;
  SVal tsv = C.getState()->getSVal(DRE);
  // Get the MemRegion associated with the container instance.
  const MemRegion *MR = tsv.getAsRegion();
  if (!MR)
    return;
  // If we are calling a function that invalidates iterators, mark them
  // appropriately by finding matching instances.
  const ProgramState *state = C.getState();
  StringRef mName = ME->getMemberDecl()->getName();
  if (llvm::StringSwitch<bool>(mName)
      .Cases("insert", "reserve", "push_back", true)
      .Cases("erase", "pop_back", "clear", "resize", true)
      .Default(false)) {
    // If there was a 'reserve' call, assume iterators are good.
    if (!state->contains<CalledReserved>(MR))
      state = invalidateIterators(state, MR, ME);
  }
  // Keep track of instances that have called 'reserve'
  // note: do this after we invalidate any iterators by calling 
  // 'reserve' itself.
  if (mName == "reserve")
    state = state->add<CalledReserved>(MR);
  
  if (state != C.getState())
    C.addTransition(state);
}

