clang API Documentation
00001 //===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- 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 declares BugReporterVisitors, which are used to generate enhanced 00011 // diagnostic traces. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H 00016 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H 00017 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 00019 #include "llvm/ADT/FoldingSet.h" 00020 00021 namespace clang { 00022 00023 namespace ento { 00024 00025 class BugReport; 00026 class BugReporterContext; 00027 class ExplodedNode; 00028 class MemRegion; 00029 class PathDiagnosticPiece; 00030 00031 /// \brief BugReporterVisitors are used to add custom diagnostics along a path. 00032 /// 00033 /// Custom visitors should subclass the BugReporterVisitorImpl class for a 00034 /// default implementation of the clone() method. 00035 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00036 /// default implementation of clone() will NOT do the right thing, and you 00037 /// will have to provide your own implementation.) 00038 class BugReporterVisitor : public llvm::FoldingSetNode { 00039 public: 00040 virtual ~BugReporterVisitor(); 00041 00042 /// \brief Returns a copy of this BugReporter. 00043 /// 00044 /// Custom BugReporterVisitors should not override this method directly. 00045 /// Instead, they should inherit from BugReporterVisitorImpl and provide 00046 /// a protected or public copy constructor. 00047 /// 00048 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00049 /// default implementation of clone() will NOT do the right thing, and you 00050 /// will have to provide your own implementation.) 00051 virtual std::unique_ptr<BugReporterVisitor> clone() const = 0; 00052 00053 /// \brief Return a diagnostic piece which should be associated with the 00054 /// given node. 00055 /// 00056 /// The last parameter can be used to register a new visitor with the given 00057 /// BugReport while processing a node. 00058 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, 00059 const ExplodedNode *Pred, 00060 BugReporterContext &BRC, 00061 BugReport &BR) = 0; 00062 00063 /// \brief Provide custom definition for the final diagnostic piece on the 00064 /// path - the piece, which is displayed before the path is expanded. 00065 /// 00066 /// If returns NULL the default implementation will be used. 00067 /// Also note that at most one visitor of a BugReport should generate a 00068 /// non-NULL end of path diagnostic piece. 00069 virtual std::unique_ptr<PathDiagnosticPiece> 00070 getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); 00071 00072 virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; 00073 00074 /// \brief Generates the default final diagnostic piece. 00075 static std::unique_ptr<PathDiagnosticPiece> 00076 getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, 00077 BugReport &BR); 00078 }; 00079 00080 /// This class provides a convenience implementation for clone() using the 00081 /// Curiously-Recurring Template Pattern. If you are implementing a custom 00082 /// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public 00083 /// or protected copy constructor. 00084 /// 00085 /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 00086 /// default implementation of clone() will NOT do the right thing, and you 00087 /// will have to provide your own implementation.) 00088 template <class DERIVED> 00089 class BugReporterVisitorImpl : public BugReporterVisitor { 00090 std::unique_ptr<BugReporterVisitor> clone() const override { 00091 return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this)); 00092 } 00093 }; 00094 00095 class FindLastStoreBRVisitor 00096 : public BugReporterVisitorImpl<FindLastStoreBRVisitor> 00097 { 00098 const MemRegion *R; 00099 SVal V; 00100 bool Satisfied; 00101 00102 /// If the visitor is tracking the value directly responsible for the 00103 /// bug, we are going to employ false positive suppression. 00104 bool EnableNullFPSuppression; 00105 00106 public: 00107 /// Creates a visitor for every VarDecl inside a Stmt and registers it with 00108 /// the BugReport. 00109 static void registerStatementVarDecls(BugReport &BR, const Stmt *S, 00110 bool EnableNullFPSuppression); 00111 00112 FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R, 00113 bool InEnableNullFPSuppression) 00114 : R(R), 00115 V(V), 00116 Satisfied(false), 00117 EnableNullFPSuppression(InEnableNullFPSuppression) {} 00118 00119 void Profile(llvm::FoldingSetNodeID &ID) const override; 00120 00121 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00122 const ExplodedNode *PrevN, 00123 BugReporterContext &BRC, 00124 BugReport &BR) override; 00125 }; 00126 00127 class TrackConstraintBRVisitor 00128 : public BugReporterVisitorImpl<TrackConstraintBRVisitor> 00129 { 00130 DefinedSVal Constraint; 00131 bool Assumption; 00132 bool IsSatisfied; 00133 bool IsZeroCheck; 00134 00135 /// We should start tracking from the last node along the path in which the 00136 /// value is constrained. 00137 bool IsTrackingTurnedOn; 00138 00139 public: 00140 TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) 00141 : Constraint(constraint), Assumption(assumption), IsSatisfied(false), 00142 IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), 00143 IsTrackingTurnedOn(false) {} 00144 00145 void Profile(llvm::FoldingSetNodeID &ID) const override; 00146 00147 /// Return the tag associated with this visitor. This tag will be used 00148 /// to make all PathDiagnosticPieces created by this visitor. 00149 static const char *getTag(); 00150 00151 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00152 const ExplodedNode *PrevN, 00153 BugReporterContext &BRC, 00154 BugReport &BR) override; 00155 00156 private: 00157 /// Checks if the constraint is valid in the current state. 00158 bool isUnderconstrained(const ExplodedNode *N) const; 00159 00160 }; 00161 00162 /// \class NilReceiverBRVisitor 00163 /// \brief Prints path notes when a message is sent to a nil receiver. 00164 class NilReceiverBRVisitor 00165 : public BugReporterVisitorImpl<NilReceiverBRVisitor> { 00166 public: 00167 00168 void Profile(llvm::FoldingSetNodeID &ID) const override { 00169 static int x = 0; 00170 ID.AddPointer(&x); 00171 } 00172 00173 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00174 const ExplodedNode *PrevN, 00175 BugReporterContext &BRC, 00176 BugReport &BR) override; 00177 00178 /// If the statement is a message send expression with nil receiver, returns 00179 /// the receiver expression. Returns NULL otherwise. 00180 static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N); 00181 }; 00182 00183 /// Visitor that tries to report interesting diagnostics from conditions. 00184 class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { 00185 public: 00186 void Profile(llvm::FoldingSetNodeID &ID) const override { 00187 static int x = 0; 00188 ID.AddPointer(&x); 00189 } 00190 00191 /// Return the tag associated with this visitor. This tag will be used 00192 /// to make all PathDiagnosticPieces created by this visitor. 00193 static const char *getTag(); 00194 00195 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00196 const ExplodedNode *Prev, 00197 BugReporterContext &BRC, 00198 BugReport &BR) override; 00199 00200 PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, 00201 const ExplodedNode *Prev, 00202 BugReporterContext &BRC, 00203 BugReport &BR); 00204 00205 PathDiagnosticPiece *VisitTerminator(const Stmt *Term, 00206 const ExplodedNode *N, 00207 const CFGBlock *srcBlk, 00208 const CFGBlock *dstBlk, 00209 BugReport &R, 00210 BugReporterContext &BRC); 00211 00212 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00213 bool tookTrue, 00214 BugReporterContext &BRC, 00215 BugReport &R, 00216 const ExplodedNode *N); 00217 00218 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00219 const DeclRefExpr *DR, 00220 const bool tookTrue, 00221 BugReporterContext &BRC, 00222 BugReport &R, 00223 const ExplodedNode *N); 00224 00225 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 00226 const BinaryOperator *BExpr, 00227 const bool tookTrue, 00228 BugReporterContext &BRC, 00229 BugReport &R, 00230 const ExplodedNode *N); 00231 00232 PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString, 00233 const Expr *CondVarExpr, 00234 const bool tookTrue, 00235 BugReporterContext &BRC, 00236 BugReport &R, 00237 const ExplodedNode *N); 00238 00239 bool patternMatch(const Expr *Ex, 00240 raw_ostream &Out, 00241 BugReporterContext &BRC, 00242 BugReport &R, 00243 const ExplodedNode *N, 00244 Optional<bool> &prunable); 00245 }; 00246 00247 /// \brief Suppress reports that might lead to known false positives. 00248 /// 00249 /// Currently this suppresses reports based on locations of bugs. 00250 class LikelyFalsePositiveSuppressionBRVisitor 00251 : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> { 00252 public: 00253 static void *getTag() { 00254 static int Tag = 0; 00255 return static_cast<void *>(&Tag); 00256 } 00257 00258 void Profile(llvm::FoldingSetNodeID &ID) const override { 00259 ID.AddPointer(getTag()); 00260 } 00261 00262 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00263 const ExplodedNode *Prev, 00264 BugReporterContext &BRC, 00265 BugReport &BR) override { 00266 return nullptr; 00267 } 00268 00269 std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, 00270 const ExplodedNode *N, 00271 BugReport &BR) override; 00272 }; 00273 00274 /// \brief When a region containing undefined value or '0' value is passed 00275 /// as an argument in a call, marks the call as interesting. 00276 /// 00277 /// As a result, BugReporter will not prune the path through the function even 00278 /// if the region's contents are not modified/accessed by the call. 00279 class UndefOrNullArgVisitor 00280 : public BugReporterVisitorImpl<UndefOrNullArgVisitor> { 00281 00282 /// The interesting memory region this visitor is tracking. 00283 const MemRegion *R; 00284 00285 public: 00286 UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {} 00287 00288 void Profile(llvm::FoldingSetNodeID &ID) const override { 00289 static int Tag = 0; 00290 ID.AddPointer(&Tag); 00291 ID.AddPointer(R); 00292 } 00293 00294 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 00295 const ExplodedNode *PrevN, 00296 BugReporterContext &BRC, 00297 BugReport &BR) override; 00298 }; 00299 00300 class SuppressInlineDefensiveChecksVisitor 00301 : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> 00302 { 00303 /// The symbolic value for which we are tracking constraints. 00304 /// This value is constrained to null in the end of path. 00305 DefinedSVal V; 00306 00307 /// Track if we found the node where the constraint was first added. 00308 bool IsSatisfied; 00309 00310 /// Since the visitors can be registered on nodes previous to the last 00311 /// node in the BugReport, but the path traversal always starts with the last 00312 /// node, the visitor invariant (that we start with a node in which V is null) 00313 /// might not hold when node visitation starts. We are going to start tracking 00314 /// from the last node in which the value is null. 00315 bool IsTrackingTurnedOn; 00316 00317 public: 00318 SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); 00319 00320 void Profile(llvm::FoldingSetNodeID &ID) const override; 00321 00322 /// Return the tag associated with this visitor. This tag will be used 00323 /// to make all PathDiagnosticPieces created by this visitor. 00324 static const char *getTag(); 00325 00326 PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, 00327 const ExplodedNode *Pred, 00328 BugReporterContext &BRC, 00329 BugReport &BR) override; 00330 }; 00331 00332 namespace bugreporter { 00333 00334 /// Attempts to add visitors to trace a null or undefined value back to its 00335 /// point of origin, whether it is a symbol constrained to null or an explicit 00336 /// assignment. 00337 /// 00338 /// \param N A node "downstream" from the evaluation of the statement. 00339 /// \param S The statement whose value is null or undefined. 00340 /// \param R The bug report to which visitors should be attached. 00341 /// \param IsArg Whether the statement is an argument to an inlined function. 00342 /// If this is the case, \p N \em must be the CallEnter node for 00343 /// the function. 00344 /// \param EnableNullFPSuppression Whether we should employ false positive 00345 /// suppression (inlined defensive checks, returned null). 00346 /// 00347 /// \return Whether or not the function was able to add visitors for this 00348 /// statement. Note that returning \c true does not actually imply 00349 /// that any visitors were added. 00350 bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, 00351 bool IsArg = false, 00352 bool EnableNullFPSuppression = true); 00353 00354 const Expr *getDerefExpr(const Stmt *S); 00355 const Stmt *GetDenomExpr(const ExplodedNode *N); 00356 const Stmt *GetRetValExpr(const ExplodedNode *N); 00357 bool isDeclRefExprToReference(const Expr *E); 00358 00359 00360 } // end namespace clang 00361 } // end namespace ento 00362 } // end namespace bugreporter 00363 00364 00365 #endif