//===-- StreamChecker.cpp -----------------------------------------*- C++ -*--//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines checkers that model and check stream handling functions.
//
//===----------------------------------------------------------------------===//

#include "GRExprEngineExperimentalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRState.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "clang/Checker/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h"

using namespace clang;

namespace {

struct StreamState {
  enum Kind { Opened, Closed, OpenFailed, Escaped } K;
  const Stmt *S;

  StreamState(Kind k, const Stmt *s) : K(k), S(s) {}

  bool isOpened() const { return K == Opened; }
  bool isClosed() const { return K == Closed; }
  //bool isOpenFailed() const { return K == OpenFailed; }
  //bool isEscaped() const { return K == Escaped; }

  bool operator==(const StreamState &X) const {
    return K == X.K && S == X.S;
  }

  static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
  static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
  static StreamState getOpenFailed(const Stmt *s) { 
    return StreamState(OpenFailed, s); 
  }
  static StreamState getEscaped(const Stmt *s) {
    return StreamState(Escaped, s);
  }

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

class StreamChecker : public CheckerVisitor<StreamChecker> {
  IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite, 
                 *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,  
                 *II_clearerr, *II_feof, *II_ferror, *II_fileno;
  BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;

public:
  StreamChecker() 
    : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0), 
      II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0), 
      II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0), 
      BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0), 
      BT_ResourceLeak(0) {}

  static void *getTag() {
    static int x;
    return &x;
  }

  virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
  void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
  void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
  void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);

private:
  void Fopen(CheckerContext &C, const CallExpr *CE);
  void Tmpfile(CheckerContext &C, const CallExpr *CE);
  void Fclose(CheckerContext &C, const CallExpr *CE);
  void Fread(CheckerContext &C, const CallExpr *CE);
  void Fwrite(CheckerContext &C, const CallExpr *CE);
  void Fseek(CheckerContext &C, const CallExpr *CE);
  void Ftell(CheckerContext &C, const CallExpr *CE);
  void Rewind(CheckerContext &C, const CallExpr *CE);
  void Fgetpos(CheckerContext &C, const CallExpr *CE);
  void Fsetpos(CheckerContext &C, const CallExpr *CE);
  void Clearerr(CheckerContext &C, const CallExpr *CE);
  void Feof(CheckerContext &C, const CallExpr *CE);
  void Ferror(CheckerContext &C, const CallExpr *CE);
  void Fileno(CheckerContext &C, const CallExpr *CE);

  void OpenFileAux(CheckerContext &C, const CallExpr *CE);
  
  const GRState *CheckNullStream(SVal SV, const GRState *state, 
                                 CheckerContext &C);
  const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state, 
                                 CheckerContext &C);
};

} // end anonymous namespace

namespace clang {
  template <>
  struct GRStateTrait<StreamState> 
    : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
    static void *GDMIndex() { return StreamChecker::getTag(); }
  };
}

void clang::RegisterStreamChecker(GRExprEngine &Eng) {
  Eng.registerCheck(new StreamChecker());
}

bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  const Expr *Callee = CE->getCallee();
  SVal L = state->getSVal(Callee);
  const FunctionDecl *FD = L.getAsFunctionDecl();
  if (!FD)
    return false;

  ASTContext &Ctx = C.getASTContext();
  if (!II_fopen)
    II_fopen = &Ctx.Idents.get("fopen");
  if (!II_tmpfile)
    II_tmpfile = &Ctx.Idents.get("tmpfile");
  if (!II_fclose)
    II_fclose = &Ctx.Idents.get("fclose");
  if (!II_fread)
    II_fread = &Ctx.Idents.get("fread");
  if (!II_fwrite)
    II_fwrite = &Ctx.Idents.get("fwrite");
  if (!II_fseek)
    II_fseek = &Ctx.Idents.get("fseek");
  if (!II_ftell)
    II_ftell = &Ctx.Idents.get("ftell");
  if (!II_rewind)
    II_rewind = &Ctx.Idents.get("rewind");
  if (!II_fgetpos)
    II_fgetpos = &Ctx.Idents.get("fgetpos");
  if (!II_fsetpos)
    II_fsetpos = &Ctx.Idents.get("fsetpos");
  if (!II_clearerr)
    II_clearerr = &Ctx.Idents.get("clearerr");
  if (!II_feof)
    II_feof = &Ctx.Idents.get("feof");
  if (!II_ferror)
    II_ferror = &Ctx.Idents.get("ferror");
  if (!II_fileno)
    II_fileno = &Ctx.Idents.get("fileno");

  if (FD->getIdentifier() == II_fopen) {
    Fopen(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_tmpfile) {
    Tmpfile(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fclose) {
    Fclose(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fread) {
    Fread(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fwrite) {
    Fwrite(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fseek) {
    Fseek(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_ftell) {
    Ftell(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_rewind) {
    Rewind(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fgetpos) {
    Fgetpos(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fsetpos) {
    Fsetpos(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_clearerr) {
    Clearerr(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_feof) {
    Feof(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_ferror) {
    Ferror(C, CE);
    return true;
  }
  if (FD->getIdentifier() == II_fileno) {
    Fileno(C, CE);
    return true;
  }

  return false;
}

void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
  OpenFileAux(C, CE);
}

void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
  OpenFileAux(C, CE);
}

void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
  ValueManager &ValMgr = C.getValueManager();
  DefinedSVal RetVal = cast<DefinedSVal>(ValMgr.getConjuredSymbolVal(0, CE, 
                                                                     Count));
  state = state->BindExpr(CE, RetVal);
  
  ConstraintManager &CM = C.getConstraintManager();
  // Bifurcate the state into two: one with a valid FILE* pointer, the other
  // with a NULL.
  const GRState *stateNotNull, *stateNull;
  llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, RetVal);
  
  if (SymbolRef Sym = RetVal.getAsSymbol()) {
    // if RetVal is not NULL, set the symbol's state to Opened.
    stateNotNull =
      stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE));
    stateNull =
      stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE));

    C.addTransition(stateNotNull);
    C.addTransition(stateNull);
  }
}

void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = CheckDoubleClose(CE, C.getState(), C);
  if (state)
    C.addTransition(state);
}

void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
    return;
}

void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
    return;
}

void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
    return;
  // Check the legality of the 'whence' argument of 'fseek'.
  SVal Whence = state->getSVal(CE->getArg(2));
  bool WhenceIsLegal = true;
  const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
  if (!CI)
    WhenceIsLegal = false;

  int64_t x = CI->getValue().getSExtValue();
  if (!(x == 0 || x == 1 || x == 2))
    WhenceIsLegal = false;

  if (!WhenceIsLegal) {
    if (ExplodedNode *N = C.GenerateSink(state)) {
      if (!BT_illegalwhence)
        BT_illegalwhence = new BuiltinBug("Illegal whence argument",
                                     "The whence argument to fseek() should be "
                                          "SEEK_SET, SEEK_END, or SEEK_CUR.");
      BugReport *R = new BugReport(*BT_illegalwhence, 
                                   BT_illegalwhence->getDescription(), N);
      C.EmitReport(R);
    }
    return;
  }

  C.addTransition(state);
}

void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) {
  const GRState *state = C.getState();
  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
    return;
}

const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
                                    CheckerContext &C) {
  const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
  if (!DV)
    return 0;

  ConstraintManager &CM = C.getConstraintManager();
  const GRState *stateNotNull, *stateNull;
  llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);

  if (!stateNotNull && stateNull) {
    if (ExplodedNode *N = C.GenerateSink(stateNull)) {
      if (!BT_nullfp)
        BT_nullfp = new BuiltinBug("NULL stream pointer",
                                     "Stream pointer might be NULL.");
      BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
      C.EmitReport(R);
    }
    return 0;
  }
  return stateNotNull;
}

const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
                                               const GRState *state,
                                               CheckerContext &C) {
  SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
  if (!Sym)
    return state;
  
  const StreamState *SS = state->get<StreamState>(Sym);

  // If the file stream is not tracked, return.
  if (!SS)
    return state;
  
  // Check: Double close a File Descriptor could cause undefined behaviour.
  // Conforming to man-pages
  if (SS->isClosed()) {
    ExplodedNode *N = C.GenerateSink();
    if (N) {
      if (!BT_doubleclose)
        BT_doubleclose = new BuiltinBug("Double fclose",
                                        "Try to close a file Descriptor already"
                                        " closed. Cause undefined behaviour.");
      BugReport *R = new BugReport(*BT_doubleclose,
                                   BT_doubleclose->getDescription(), N);
      C.EmitReport(R);
    }
    return NULL;
  }
  
  // Close the File Descriptor.
  return state->set<StreamState>(Sym, StreamState::getClosed(CE));
}

void StreamChecker::EvalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
  for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
         E = SymReaper.dead_end(); I != E; ++I) {
    SymbolRef Sym = *I;
    const GRState *state = C.getState();
    const StreamState *SS = state->get<StreamState>(Sym);
    if (!SS)
      return;

    if (SS->isOpened()) {
      ExplodedNode *N = C.GenerateSink();
      if (N) {
        if (!BT_ResourceLeak)
          BT_ResourceLeak = new BuiltinBug("Resource Leak", 
                          "Opened File never closed. Potential Resource leak.");
        BugReport *R = new BugReport(*BT_ResourceLeak, 
                                     BT_ResourceLeak->getDescription(), N);
        C.EmitReport(R);
      }
    }
  }
}

void StreamChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
                                GRExprEngine &Eng) {
  SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
  const GRState *state = B.getState();
  typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
  SymMap M = state->get<StreamState>();
  
  for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    StreamState SS = I->second;
    if (SS.isOpened()) {
      ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
      if (N) {
        if (!BT_ResourceLeak)
          BT_ResourceLeak = new BuiltinBug("Resource Leak", 
                          "Opened File never closed. Potential Resource leak.");
        BugReport *R = new BugReport(*BT_ResourceLeak, 
                                     BT_ResourceLeak->getDescription(), N);
        Eng.getBugReporter().EmitReport(R);
      }
    }
  }
}

void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
  const Expr *RetE = S->getRetValue();
  if (!RetE)
    return;
  
  const GRState *state = C.getState();
  SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
  
  if (!Sym)
    return;
  
  const StreamState *SS = state->get<StreamState>(Sym);
  if(!SS)
    return;

  if (SS->isOpened())
    state = state->set<StreamState>(Sym, StreamState::getEscaped(S));

  C.addTransition(state);
}
