clang  10.0.0git
CheckerContext.h
Go to the documentation of this file.
1 //== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines CheckerContext that provides contextual info for
10 // path-sensitive checkers.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
16 
19 
20 namespace clang {
21 namespace ento {
22 
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 
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 
56  return Eng.getAnalysisManager();
57  }
58 
60  return Eng.getConstraintManager();
61  }
62 
64  return Eng.getStoreManager();
65  }
66 
67  /// 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  const ProgramStateRef &getState() const { return Pred->getState(); }
72 
73  /// 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  /// Returns the number of times the current block has been visited
78  /// along the analyzed path.
79  unsigned blockCount() const {
80  return NB.getContext().blockCount();
81  }
82 
84  return Eng.getContext();
85  }
86 
87  const LangOptions &getLangOpts() const {
88  return Eng.getContext().getLangOpts();
89  }
90 
92  return Pred->getLocationContext();
93  }
94 
96  return Pred->getStackFrame();
97  }
98 
99  /// Return true if the current LocationContext has no caller context.
100  bool inTopFrame() const { return getLocationContext()->inTopFrame(); }
101 
103  return Eng.getBugReporter();
104  }
105 
107  return getBugReporter().getSourceManager();
108  }
109 
111  return Eng.getSValBuilder();
112  }
113 
115  return getSValBuilder().getSymbolManager();
116  }
117 
119  return Eng.getStateManager();
120  }
121 
123  return Pred->getLocationContext()->getAnalysisDeclContext();
124  }
125 
126  /// Get the blockID.
127  unsigned getBlockID() const {
128  return NB.getContext().getBlock()->getBlockID();
129  }
130 
131  /// If the given node corresponds to a PostStore program point,
132  /// retrieve the location region as it was uttered in the code.
133  ///
134  /// This utility can be useful for generating extensive diagnostics, for
135  /// example, for finding variables that the given symbol was assigned to.
137  ProgramPoint L = N->getLocation();
138  if (Optional<PostStore> PSL = L.getAs<PostStore>())
139  return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
140  return nullptr;
141  }
142 
143  /// Get the value of arbitrary expressions at this point in the path.
144  SVal getSVal(const Stmt *S) const {
145  return Pred->getSVal(S);
146  }
147 
148  /// Returns true if the value of \p E is greater than or equal to \p
149  /// Val under unsigned comparison
150  bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
151 
152  /// Returns true if the value of \p E is negative.
153  bool isNegative(const Expr *E);
154 
155  /// Generates a new transition in the program state graph
156  /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
157  ///
158  /// @param State The state of the generated node. If not specified, the state
159  /// will not be changed, but the new node will have the checker's tag.
160  /// @param Tag The tag is used to uniquely identify the creation site. If no
161  /// tag is specified, a default tag, unique to the given checker,
162  /// will be used. Tags are used to prevent states generated at
163  /// different sites from caching out.
165  const ProgramPointTag *Tag = nullptr) {
166  return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
167  }
168 
169  /// Generates a new transition with the given predecessor.
170  /// Allows checkers to generate a chain of nodes.
171  ///
172  /// @param State The state of the generated node.
173  /// @param Pred The transition will be generated from the specified Pred node
174  /// to the newly generated node.
175  /// @param Tag The tag to uniquely identify the creation site.
177  ExplodedNode *Pred,
178  const ProgramPointTag *Tag = nullptr) {
179  return addTransitionImpl(State, false, Pred, Tag);
180  }
181 
182  /// Generate a sink node. Generating a sink stops exploration of the
183  /// given path. To create a sink node for the purpose of reporting an error,
184  /// checkers should use generateErrorNode() instead.
186  const ProgramPointTag *Tag = nullptr) {
187  return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
188  }
189 
190  /// Generate a transition to a node that will be used to report
191  /// an error. This node will be a sink. That is, it will stop exploration of
192  /// the given path.
193  ///
194  /// @param State The state of the generated node.
195  /// @param Tag The tag to uniquely identify the creation site. If null,
196  /// the default tag for the checker will be used.
198  const ProgramPointTag *Tag = nullptr) {
199  return generateSink(State, Pred,
200  (Tag ? Tag : Location.getTag()));
201  }
202 
203  /// Generate a transition to a node that will be used to report
204  /// an error. This node will not be a sink. That is, exploration will
205  /// continue along this path.
206  ///
207  /// @param State The state of the generated node.
208  /// @param Tag The tag to uniquely identify the creation site. If null,
209  /// the default tag for the checker will be used.
210  ExplodedNode *
212  const ProgramPointTag *Tag = nullptr) {
213  return addTransition(State, (Tag ? Tag : Location.getTag()));
214  }
215 
216  /// Generate a transition to a node that will be used to report
217  /// an error. This node will not be a sink. That is, exploration will
218  /// continue along this path.
219  ///
220  /// @param State The state of the generated node.
221  /// @param Pred The transition will be generated from the specified Pred node
222  /// to the newly generated node.
223  /// @param Tag The tag to uniquely identify the creation site. If null,
224  /// the default tag for the checker will be used.
225  ExplodedNode *
227  ExplodedNode *Pred,
228  const ProgramPointTag *Tag = nullptr) {
229  return addTransition(State, Pred, (Tag ? Tag : Location.getTag()));
230  }
231 
232  /// Emit the diagnostics report.
233  void emitReport(std::unique_ptr<BugReport> R) {
234  Changed = true;
235  Eng.getBugReporter().emitReport(std::move(R));
236  }
237 
238  /// Produce a program point tag that displays an additional path note
239  /// to the user. This is a lightweight alternative to the
240  /// BugReporterVisitor mechanism: instead of visiting the bug report
241  /// node-by-node to restore the sequence of events that led to discovering
242  /// a bug, you can add notes as you add your transitions.
243  ///
244  /// @param Cb Callback with 'BugReporterContext &, BugReport &' parameters.
245  /// @param IsPrunable Whether the note is prunable. It allows BugReporter
246  /// to omit the note from the report if it would make the displayed
247  /// bug path significantly shorter.
248  const NoteTag *getNoteTag(NoteTag::Callback &&Cb, bool IsPrunable = false) {
249  return Eng.getNoteTags().makeNoteTag(std::move(Cb), IsPrunable);
250  }
251 
252  /// A shorthand version of getNoteTag that doesn't require you to accept
253  /// the 'BugReporterContext' argument when you don't need it.
254  ///
255  /// @param Cb Callback only with 'BugReport &' parameter.
256  /// @param IsPrunable Whether the note is prunable. It allows BugReporter
257  /// to omit the note from the report if it would make the displayed
258  /// bug path significantly shorter.
259  const NoteTag *getNoteTag(std::function<std::string(BugReport &)> &&Cb,
260  bool IsPrunable = false) {
261  return getNoteTag(
262  [Cb](BugReporterContext &, BugReport &BR) { return Cb(BR); },
263  IsPrunable);
264  }
265 
266  /// A shorthand version of getNoteTag that doesn't require you to accept
267  /// the arguments when you don't need it.
268  ///
269  /// @param Cb Callback without parameters.
270  /// @param IsPrunable Whether the note is prunable. It allows BugReporter
271  /// to omit the note from the report if it would make the displayed
272  /// bug path significantly shorter.
273  const NoteTag *getNoteTag(std::function<std::string()> &&Cb,
274  bool IsPrunable = false) {
275  return getNoteTag([Cb](BugReporterContext &, BugReport &) { return Cb(); },
276  IsPrunable);
277  }
278 
279  /// A shorthand version of getNoteTag that accepts a plain note.
280  ///
281  /// @param Note The note.
282  /// @param IsPrunable Whether the note is prunable. It allows BugReporter
283  /// to omit the note from the report if it would make the displayed
284  /// bug path significantly shorter.
285  const NoteTag *getNoteTag(StringRef Note, bool IsPrunable = false) {
286  return getNoteTag(
287  [Note](BugReporterContext &, BugReport &) { return Note; }, IsPrunable);
288  }
289 
290  /// Returns the word that should be used to refer to the declaration
291  /// in the report.
292  StringRef getDeclDescription(const Decl *D);
293 
294  /// Get the declaration of the called function (path-sensitive).
295  const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
296 
297  /// Get the name of the called function (path-sensitive).
298  StringRef getCalleeName(const FunctionDecl *FunDecl) const;
299 
300  /// Get the identifier of the called function (path-sensitive).
301  const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
302  const FunctionDecl *FunDecl = getCalleeDecl(CE);
303  if (FunDecl)
304  return FunDecl->getIdentifier();
305  else
306  return nullptr;
307  }
308 
309  /// Get the name of the called function (path-sensitive).
310  StringRef getCalleeName(const CallExpr *CE) const {
311  const FunctionDecl *FunDecl = getCalleeDecl(CE);
312  return getCalleeName(FunDecl);
313  }
314 
315  /// Returns true if the callee is an externally-visible function in the
316  /// top-level namespace, such as \c malloc.
317  ///
318  /// If a name is provided, the function must additionally match the given
319  /// name.
320  ///
321  /// Note that this deliberately excludes C++ library functions in the \c std
322  /// namespace, but will include C library functions accessed through the
323  /// \c std namespace. This also does not check if the function is declared
324  /// as 'extern "C"', or if it uses C++ name mangling.
325  static bool isCLibraryFunction(const FunctionDecl *FD,
326  StringRef Name = StringRef());
327 
328  /// Depending on wither the location corresponds to a macro, return
329  /// either the macro name or the token spelling.
330  ///
331  /// This could be useful when checkers' logic depends on whether a function
332  /// is called with a given macro argument. For example:
333  /// s = socket(AF_INET,..)
334  /// If AF_INET is a macro, the result should be treated as a source of taint.
335  ///
336  /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
338 
339 private:
340  ExplodedNode *addTransitionImpl(ProgramStateRef State,
341  bool MarkAsSink,
342  ExplodedNode *P = nullptr,
343  const ProgramPointTag *Tag = nullptr) {
344  // The analyzer may stop exploring if it sees a state it has previously
345  // visited ("cache out"). The early return here is a defensive check to
346  // prevent accidental caching out by checker API clients. Unless there is a
347  // tag or the client checker has requested that the generated node be
348  // marked as a sink, we assume that a client requesting a transition to a
349  // state that is the same as the predecessor state has made a mistake. We
350  // return the predecessor rather than cache out.
351  //
352  // TODO: We could potentially change the return to an assertion to alert
353  // clients to their mistake, but several checkers (including
354  // DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation)
355  // rely upon the defensive behavior and would need to be updated.
356  if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
357  return Pred;
358 
359  Changed = true;
360  const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
361  if (!P)
362  P = Pred;
363 
365  if (MarkAsSink)
366  node = NB.generateSink(LocalLoc, State, P);
367  else
368  node = NB.generateNode(LocalLoc, State, P);
369  return node;
370  }
371 };
372 
373 } // end GR namespace
374 
375 } // end clang namespace
376 
377 #endif
Represents a function declaration or definition.
Definition: Decl.h:1783
StringRef getCalleeName(const CallExpr *CE) const
Get the name of the called function (path-sensitive).
const NoteTag * getNoteTag(NoteTag::Callback &&Cb, bool IsPrunable=false)
Produce a program point tag that displays an additional path note to the user.
SymbolManager & getSymbolManager()
Definition: SValBuilder.h:171
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path...
Definition: CoreEngine.h:220
Stmt - This represents one statement.
Definition: Stmt.h:66
const NoteTag * makeNoteTag(Callback &&Cb, bool IsPrunable=false)
Definition: BugReporter.h:764
unsigned getBlockID() const
Definition: CFG.h:1075
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
StringRef P
ProgramPoint withTag(const ProgramPointTag *tag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
Definition: ProgramPoint.h:132
StringRef getDeclDescription(const Decl *D)
Returns the word that should be used to refer to the declaration in the report.
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
AnalysisManager & getAnalysisManager()
const ProgramStateRef & getState() const
CheckerContext(NodeBuilder &builder, ExprEngine &eng, ExplodedNode *pred, const ProgramPoint &loc, bool wasInlined=false)
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:244
StringRef getCalleeName(const FunctionDecl *FunDecl) const
Get the name of the called function (path-sensitive).
One of these records is kept for each identifier that is lexed.
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
bool isGreaterOrEqual(const Expr *E, unsigned long long Val)
Returns true if the value of E is greater than or equal to Val under unsigned comparison.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:168
LineState State
AnalysisDeclContext contains the context data for the function or method under analysis.
std::function< std::string(BugReporterContext &, BugReport &)> Callback
Definition: BugReporter.h:725
Represents a program point after a store evaluation.
Definition: ProgramPoint.h:431
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:53
BugReporter & getBugReporter()
NoteTag::Factory & getNoteTags()
Definition: ExprEngine.h:400
ProgramStateManager & getStateManager()
const LocationContext * getLocationContext() const
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
const NoteTag * getNoteTag(std::function< std::string(BugReport &)> &&Cb, bool IsPrunable=false)
A shorthand version of getNoteTag that doesn&#39;t require you to accept the &#39;BugReporterContext&#39; argumen...
const IdentifierInfo * getCalleeIdentifier(const CallExpr *CE) const
Get the identifier of the called function (path-sensitive).
const SourceManager & getSourceManager()
ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a sink in the ExplodedGraph.
Definition: CoreEngine.h:300
This represents one expression.
Definition: Expr.h:108
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name=StringRef())
Returns true if the callee is an externally-visible function in the top-level namespace, such as malloc.
This is the simplest builder which generates nodes in the ExplodedGraph.
Definition: CoreEngine.h:236
ExplodedNode * addTransition(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generates a new transition with the given predecessor.
SymbolManager & getSymbolManager()
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
Definition: ExprEngine.h:182
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
The tag upon which the TagVisitor reacts.
Definition: BugReporter.h:722
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
const NoteTag * getNoteTag(std::function< std::string()> &&Cb, bool IsPrunable=false)
A shorthand version of getNoteTag that doesn&#39;t require you to accept the arguments when you don&#39;t nee...
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:576
#define false
Definition: stdbool.h:17
StoreManager & getStoreManager()
Encodes a location in the source.
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
Definition: ProgramPoint.h:39
AnalysisManager & getAnalysisManager() override
Definition: ExprEngine.h:184
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
BugReporter & getBugReporter()
Definition: ExprEngine.h:196
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
unsigned getBlockID() const
Get the blockID.
Dataflow Directional Tag Classes.
SValBuilder & getSValBuilder()
Definition: ExprEngine.h:194
StoreManager & getStoreManager()
Definition: ExprEngine.h:386
const NodeBuilderContext & getContext()
Definition: CoreEngine.h:326
const NoteTag * getNoteTag(StringRef Note, bool IsPrunable=false)
A shorthand version of getNoteTag that accepts a plain note.
StringRef getMacroNameOrSpelling(SourceLocation &Loc)
Depending on wither the location corresponds to a macro, return either the macro name or the token sp...
const ProgramPointTag * getTag() const
Definition: ProgramPoint.h:177
ProgramStateManager & getStateManager() override
Definition: ExprEngine.h:384
const StackFrameContext * getStackFrame() const
const ProgramStateRef & getState() const
bool isNegative(const Expr *E)
Returns true if the value of E is negative.
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a node in the ExplodedGraph.
Definition: CoreEngine.h:289
AnalysisDeclContext * getCurrentAnalysisDeclContext() const
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2546
static const MemRegion * getLocationRegionIfPostStore(const ExplodedNode *N)
If the given node corresponds to a PostStore program point, retrieve the location region as it was ut...
const StackFrameContext * getStackFrame() const
RangeSelector node(std::string ID)
Selects a node, including trailing semicolon (for non-expression statements).
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:151
This class provides an interface through which checkers can create individual bug reports...
Definition: BugReporter.h:119
ConstraintManager & getConstraintManager()
Definition: ExprEngine.h:388
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getLocationContext() const
bool isDifferent()
Check if the checker changed the state of the execution; ex: added a new transition or a bug report...
const LangOptions & getLangOpts() const
Definition: ASTContext.h:724
This class handles loading and caching of source files into memory.
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
Definition: CoreEngine.h:216
const LangOptions & getLangOpts() const
const SourceManager & getSourceManager()
Definition: BugReporter.h:607