Home | History | Annotate | Download | only in PathSensitive
      1 //== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines CheckerContext that provides contextual info for
     11 // path-sensitive checkers.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
     16 #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
     17 
     18 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
     19 
     20 namespace clang {
     21 namespace ento {
     22 
     23 class CheckerContext {
     24   ExprEngine &Eng;
     25   /// The current exploded(symbolic execution) graph node.
     26   ExplodedNode *Pred;
     27   /// The flag is true if the (state of the execution) has been modified
     28   /// by the checker using this context. For example, a new transition has been
     29   /// added or a bug report issued.
     30   bool Changed;
     31   /// The tagged location, which is used to generate all new nodes.
     32   const ProgramPoint Location;
     33   NodeBuilder &NB;
     34 
     35 public:
     36   /// If we are post visiting a call, this flag will be set if the
     37   /// call was inlined.  In all other cases it will be false.
     38   const bool wasInlined;
     39 
     40   CheckerContext(NodeBuilder &builder,
     41                  ExprEngine &eng,
     42                  ExplodedNode *pred,
     43                  const ProgramPoint &loc,
     44                  bool wasInlined = false)
     45     : Eng(eng),
     46       Pred(pred),
     47       Changed(false),
     48       Location(loc),
     49       NB(builder),
     50       wasInlined(wasInlined) {
     51     assert(Pred->getState() &&
     52            "We should not call the checkers on an empty state.");
     53   }
     54 
     55   AnalysisManager &getAnalysisManager() {
     56     return Eng.getAnalysisManager();
     57   }
     58 
     59   ConstraintManager &getConstraintManager() {
     60     return Eng.getConstraintManager();
     61   }
     62 
     63   StoreManager &getStoreManager() {
     64     return Eng.getStoreManager();
     65   }
     66 
     67   /// \brief Returns the previous node in the exploded graph, which includes
     68   /// the state of the program before the checker ran. Note, checkers should
     69   /// not retain the node in their state since the nodes might get invalidated.
     70   ExplodedNode *getPredecessor() { return Pred; }
     71   ProgramStateRef getState() const { return Pred->getState(); }
     72 
     73   /// \brief Check if the checker changed the state of the execution; ex: added
     74   /// a new transition or a bug report.
     75   bool isDifferent() { return Changed; }
     76 
     77   /// \brief Returns the number of times the current block has been visited
     78   /// along the analyzed path.
     79   unsigned getCurrentBlockCount() const {
     80     return NB.getContext().getCurrentBlockCount();
     81   }
     82 
     83   ASTContext &getASTContext() {
     84     return Eng.getContext();
     85   }
     86 
     87   const LangOptions &getLangOpts() const {
     88     return Eng.getContext().getLangOpts();
     89   }
     90 
     91   const LocationContext *getLocationContext() const {
     92     return Pred->getLocationContext();
     93   }
     94 
     95   BugReporter &getBugReporter() {
     96     return Eng.getBugReporter();
     97   }
     98 
     99   SourceManager &getSourceManager() {
    100     return getBugReporter().getSourceManager();
    101   }
    102 
    103   SValBuilder &getSValBuilder() {
    104     return Eng.getSValBuilder();
    105   }
    106 
    107   SymbolManager &getSymbolManager() {
    108     return getSValBuilder().getSymbolManager();
    109   }
    110 
    111   bool isObjCGCEnabled() const {
    112     return Eng.isObjCGCEnabled();
    113   }
    114 
    115   ProgramStateManager &getStateManager() {
    116     return Eng.getStateManager();
    117   }
    118 
    119   AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
    120     return Pred->getLocationContext()->getAnalysisDeclContext();
    121   }
    122 
    123   /// \brief If the given node corresponds to a PostStore program point, retrieve
    124   /// the location region as it was uttered in the code.
    125   ///
    126   /// This utility can be useful for generating extensive diagnostics, for
    127   /// example, for finding variables that the given symbol was assigned to.
    128   static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
    129     ProgramPoint L = N->getLocation();
    130     if (const PostStore *PSL = dyn_cast<PostStore>(&L))
    131       return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
    132     return 0;
    133   }
    134 
    135   /// \brief Generates a new transition in the program state graph
    136   /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
    137   ///
    138   /// @param State The state of the generated node.
    139   /// @param Tag The tag is used to uniquely identify the creation site. If no
    140   ///        tag is specified, a default tag, unique to the given checker,
    141   ///        will be used. Tags are used to prevent states generated at
    142   ///        different sites from caching out.
    143   ExplodedNode *addTransition(ProgramStateRef State,
    144                               const ProgramPointTag *Tag = 0) {
    145     return addTransitionImpl(State, false, 0, Tag);
    146   }
    147 
    148   /// \brief Generates a default transition (containing checker tag but no
    149   /// checker state changes).
    150   ExplodedNode *addTransition() {
    151     return addTransition(getState());
    152   }
    153 
    154   /// \brief Generates a new transition with the given predecessor.
    155   /// Allows checkers to generate a chain of nodes.
    156   ///
    157   /// @param State The state of the generated node.
    158   /// @param Pred The transition will be generated from the specified Pred node
    159   ///             to the newly generated node.
    160   /// @param Tag The tag to uniquely identify the creation site.
    161   /// @param IsSink Mark the new node as sink, which will stop exploration of
    162   ///               the given path.
    163   ExplodedNode *addTransition(ProgramStateRef State,
    164                              ExplodedNode *Pred,
    165                              const ProgramPointTag *Tag = 0,
    166                              bool IsSink = false) {
    167     return addTransitionImpl(State, IsSink, Pred, Tag);
    168   }
    169 
    170   /// \brief Generate a sink node. Generating sink stops exploration of the
    171   /// given path.
    172   ExplodedNode *generateSink(ProgramStateRef state = 0) {
    173     return addTransitionImpl(state ? state : getState(), true);
    174   }
    175 
    176   /// \brief Emit the diagnostics report.
    177   void EmitReport(BugReport *R) {
    178     Changed = true;
    179     Eng.getBugReporter().EmitReport(R);
    180   }
    181 
    182   /// \brief Get the declaration of the called function (path-sensitive).
    183   const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
    184 
    185   /// \brief Get the name of the called function (path-sensitive).
    186   StringRef getCalleeName(const FunctionDecl *FunDecl) const;
    187 
    188   /// \brief Get the name of the called function (path-sensitive).
    189   StringRef getCalleeName(const CallExpr *CE) const {
    190     const FunctionDecl *FunDecl = getCalleeDecl(CE);
    191     return getCalleeName(FunDecl);
    192   }
    193 
    194   /// Given a function declaration and a name checks if this is a C lib
    195   /// function with the given name.
    196   bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
    197   static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name,
    198                                  ASTContext &Context);
    199 
    200   /// \brief Depending on wither the location corresponds to a macro, return
    201   /// either the macro name or the token spelling.
    202   ///
    203   /// This could be useful when checkers' logic depends on whether a function
    204   /// is called with a given macro argument. For example:
    205   ///   s = socket(AF_INET,..)
    206   /// If AF_INET is a macro, the result should be treated as a source of taint.
    207   ///
    208   /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
    209   StringRef getMacroNameOrSpelling(SourceLocation &Loc);
    210 
    211 private:
    212   ExplodedNode *addTransitionImpl(ProgramStateRef State,
    213                                  bool MarkAsSink,
    214                                  ExplodedNode *P = 0,
    215                                  const ProgramPointTag *Tag = 0) {
    216     if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
    217       return Pred;
    218 
    219     Changed = true;
    220     ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location,
    221                                         State,
    222                                         P ? P : Pred, MarkAsSink);
    223     return node;
    224   }
    225 };
    226 
    227 /// \brief A helper class which wraps a boolean value set to false by default.
    228 struct DefaultBool {
    229   bool Val;
    230   DefaultBool() : Val(false) {}
    231   operator bool() const { return Val; }
    232   DefaultBool &operator=(bool b) { Val = b; return *this; }
    233 };
    234 
    235 } // end GR namespace
    236 
    237 } // end clang namespace
    238 
    239 #endif
    240