clang API Documentation

CheckerContext.h
Go to the documentation of this file.
00001 //== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines CheckerContext that provides contextual info for
00011 // path-sensitive checkers.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
00016 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
00017 
00018 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
00020 
00021 namespace clang {
00022 namespace ento {
00023 
00024   /// Declares an immutable map of type \p NameTy, suitable for placement into
00025   /// the ProgramState. This is implementing using llvm::ImmutableMap.
00026   ///
00027   /// \code
00028   /// State = State->set<Name>(K, V);
00029   /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map.
00030   /// State = State->remove<Name>(K);
00031   /// NameTy Map = State->get<Name>();
00032   /// \endcode
00033   ///
00034   /// The macro should not be used inside namespaces, or for traits that must
00035   /// be accessible from more than one translation unit.
00036   #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
00037     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
00038                                      CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
00039 
00040   /// Declares an immutable set of type \p NameTy, suitable for placement into
00041   /// the ProgramState. This is implementing using llvm::ImmutableSet.
00042   ///
00043   /// \code
00044   /// State = State->add<Name>(E);
00045   /// State = State->remove<Name>(E);
00046   /// bool Present = State->contains<Name>(E);
00047   /// NameTy Set = State->get<Name>();
00048   /// \endcode
00049   ///
00050   /// The macro should not be used inside namespaces, or for traits that must
00051   /// be accessible from more than one translation unit.
00052   #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
00053     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
00054   
00055   /// Declares an immutable list of type \p NameTy, suitable for placement into
00056   /// the ProgramState. This is implementing using llvm::ImmutableList.
00057   ///
00058   /// \code
00059   /// State = State->add<Name>(E); // Adds to the /end/ of the list.
00060   /// bool Present = State->contains<Name>(E);
00061   /// NameTy List = State->get<Name>();
00062   /// \endcode
00063   ///
00064   /// The macro should not be used inside namespaces, or for traits that must
00065   /// be accessible from more than one translation unit.
00066   #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
00067     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
00068 
00069 
00070 class CheckerContext {
00071   ExprEngine &Eng;
00072   /// The current exploded(symbolic execution) graph node.
00073   ExplodedNode *Pred;
00074   /// The flag is true if the (state of the execution) has been modified
00075   /// by the checker using this context. For example, a new transition has been
00076   /// added or a bug report issued.
00077   bool Changed;
00078   /// The tagged location, which is used to generate all new nodes.
00079   const ProgramPoint Location;
00080   NodeBuilder &NB;
00081 
00082 public:
00083   /// If we are post visiting a call, this flag will be set if the
00084   /// call was inlined.  In all other cases it will be false.
00085   const bool wasInlined;
00086   
00087   CheckerContext(NodeBuilder &builder,
00088                  ExprEngine &eng,
00089                  ExplodedNode *pred,
00090                  const ProgramPoint &loc,
00091                  bool wasInlined = false)
00092     : Eng(eng),
00093       Pred(pred),
00094       Changed(false),
00095       Location(loc),
00096       NB(builder),
00097       wasInlined(wasInlined) {
00098     assert(Pred->getState() &&
00099            "We should not call the checkers on an empty state.");
00100   }
00101 
00102   AnalysisManager &getAnalysisManager() {
00103     return Eng.getAnalysisManager();
00104   }
00105 
00106   ConstraintManager &getConstraintManager() {
00107     return Eng.getConstraintManager();
00108   }
00109 
00110   StoreManager &getStoreManager() {
00111     return Eng.getStoreManager();
00112   }
00113   
00114   /// \brief Returns the previous node in the exploded graph, which includes
00115   /// the state of the program before the checker ran. Note, checkers should
00116   /// not retain the node in their state since the nodes might get invalidated.
00117   ExplodedNode *getPredecessor() { return Pred; }
00118   const ProgramStateRef &getState() const { return Pred->getState(); }
00119 
00120   /// \brief Check if the checker changed the state of the execution; ex: added
00121   /// a new transition or a bug report.
00122   bool isDifferent() { return Changed; }
00123 
00124   /// \brief Returns the number of times the current block has been visited
00125   /// along the analyzed path.
00126   unsigned blockCount() const {
00127     return NB.getContext().blockCount();
00128   }
00129 
00130   ASTContext &getASTContext() {
00131     return Eng.getContext();
00132   }
00133 
00134   const LangOptions &getLangOpts() const {
00135     return Eng.getContext().getLangOpts();
00136   }
00137 
00138   const LocationContext *getLocationContext() const {
00139     return Pred->getLocationContext();
00140   }
00141 
00142   const StackFrameContext *getStackFrame() const {
00143     return Pred->getStackFrame();
00144   }
00145 
00146   /// Return true if the current LocationContext has no caller context.
00147   bool inTopFrame() const { return getLocationContext()->inTopFrame();  }
00148 
00149   BugReporter &getBugReporter() {
00150     return Eng.getBugReporter();
00151   }
00152   
00153   SourceManager &getSourceManager() {
00154     return getBugReporter().getSourceManager();
00155   }
00156 
00157   SValBuilder &getSValBuilder() {
00158     return Eng.getSValBuilder();
00159   }
00160 
00161   SymbolManager &getSymbolManager() {
00162     return getSValBuilder().getSymbolManager();
00163   }
00164 
00165   bool isObjCGCEnabled() const {
00166     return Eng.isObjCGCEnabled();
00167   }
00168 
00169   ProgramStateManager &getStateManager() {
00170     return Eng.getStateManager();
00171   }
00172 
00173   AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
00174     return Pred->getLocationContext()->getAnalysisDeclContext();
00175   }
00176 
00177   /// \brief Get the blockID.
00178   unsigned getBlockID() const {
00179     return NB.getContext().getBlock()->getBlockID();
00180   }
00181 
00182   /// \brief If the given node corresponds to a PostStore program point,
00183   /// retrieve the location region as it was uttered in the code.
00184   ///
00185   /// This utility can be useful for generating extensive diagnostics, for
00186   /// example, for finding variables that the given symbol was assigned to.
00187   static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
00188     ProgramPoint L = N->getLocation();
00189     if (Optional<PostStore> PSL = L.getAs<PostStore>())
00190       return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
00191     return nullptr;
00192   }
00193 
00194   /// \brief Get the value of arbitrary expressions at this point in the path.
00195   SVal getSVal(const Stmt *S) const {
00196     return getState()->getSVal(S, getLocationContext());
00197   }
00198 
00199   /// \brief Generates a new transition in the program state graph
00200   /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
00201   ///
00202   /// @param State The state of the generated node. If not specified, the state
00203   ///        will not be changed, but the new node will have the checker's tag.
00204   /// @param Tag The tag is used to uniquely identify the creation site. If no
00205   ///        tag is specified, a default tag, unique to the given checker,
00206   ///        will be used. Tags are used to prevent states generated at
00207   ///        different sites from caching out.
00208   ExplodedNode *addTransition(ProgramStateRef State = nullptr,
00209                               const ProgramPointTag *Tag = nullptr) {
00210     return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
00211   }
00212 
00213   /// \brief Generates a new transition with the given predecessor.
00214   /// Allows checkers to generate a chain of nodes.
00215   ///
00216   /// @param State The state of the generated node.
00217   /// @param Pred The transition will be generated from the specified Pred node
00218   ///             to the newly generated node.
00219   /// @param Tag The tag to uniquely identify the creation site.
00220   ExplodedNode *addTransition(ProgramStateRef State,
00221                               ExplodedNode *Pred,
00222                               const ProgramPointTag *Tag = nullptr) {
00223     return addTransitionImpl(State, false, Pred, Tag);
00224   }
00225 
00226   /// \brief Generate a sink node. Generating a sink stops exploration of the
00227   /// given path.
00228   ExplodedNode *generateSink(ProgramStateRef State = nullptr,
00229                              ExplodedNode *Pred = nullptr,
00230                              const ProgramPointTag *Tag = nullptr) {
00231     return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
00232   }
00233 
00234   /// \brief Emit the diagnostics report.
00235   void emitReport(BugReport *R) {
00236     Changed = true;
00237     Eng.getBugReporter().emitReport(R);
00238   }
00239 
00240   /// \brief Get the declaration of the called function (path-sensitive).
00241   const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
00242 
00243   /// \brief Get the name of the called function (path-sensitive).
00244   StringRef getCalleeName(const FunctionDecl *FunDecl) const;
00245 
00246   /// \brief Get the identifier of the called function (path-sensitive).
00247   const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
00248     const FunctionDecl *FunDecl = getCalleeDecl(CE);
00249     if (FunDecl)
00250       return FunDecl->getIdentifier();
00251     else
00252       return nullptr;
00253   }
00254 
00255   /// \brief Get the name of the called function (path-sensitive).
00256   StringRef getCalleeName(const CallExpr *CE) const {
00257     const FunctionDecl *FunDecl = getCalleeDecl(CE);
00258     return getCalleeName(FunDecl);
00259   }
00260 
00261   /// \brief Returns true if the callee is an externally-visible function in the
00262   /// top-level namespace, such as \c malloc.
00263   ///
00264   /// If a name is provided, the function must additionally match the given
00265   /// name.
00266   ///
00267   /// Note that this deliberately excludes C++ library functions in the \c std
00268   /// namespace, but will include C library functions accessed through the
00269   /// \c std namespace. This also does not check if the function is declared
00270   /// as 'extern "C"', or if it uses C++ name mangling.
00271   static bool isCLibraryFunction(const FunctionDecl *FD,
00272                                  StringRef Name = StringRef());
00273 
00274   /// \brief Depending on wither the location corresponds to a macro, return 
00275   /// either the macro name or the token spelling.
00276   ///
00277   /// This could be useful when checkers' logic depends on whether a function
00278   /// is called with a given macro argument. For example:
00279   ///   s = socket(AF_INET,..)
00280   /// If AF_INET is a macro, the result should be treated as a source of taint.
00281   ///
00282   /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
00283   StringRef getMacroNameOrSpelling(SourceLocation &Loc);
00284 
00285 private:
00286   ExplodedNode *addTransitionImpl(ProgramStateRef State,
00287                                  bool MarkAsSink,
00288                                  ExplodedNode *P = nullptr,
00289                                  const ProgramPointTag *Tag = nullptr) {
00290     if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
00291       return Pred;
00292 
00293     Changed = true;
00294     const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
00295     if (!P)
00296       P = Pred;
00297 
00298     ExplodedNode *node;
00299     if (MarkAsSink)
00300       node = NB.generateSink(LocalLoc, State, P);
00301     else
00302       node = NB.generateNode(LocalLoc, State, P);
00303     return node;
00304   }
00305 };
00306 
00307 } // end GR namespace
00308 
00309 } // end clang namespace
00310 
00311 #endif