1226586Sdim//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===// 2226586Sdim// 3226586Sdim// The LLVM Compiler Infrastructure 4226586Sdim// 5226586Sdim// This file is distributed under the University of Illinois Open Source 6226586Sdim// License. See LICENSE.TXT for details. 7226586Sdim// 8226586Sdim//===----------------------------------------------------------------------===// 9226586Sdim// 10226586Sdim// This file declares BugReporterVisitors, which are used to generate enhanced 11226586Sdim// diagnostic traces. 12226586Sdim// 13226586Sdim//===----------------------------------------------------------------------===// 14226586Sdim 15226586Sdim#ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR 16226586Sdim#define LLVM_CLANG_GR_BUGREPORTERVISITOR 17226586Sdim 18226586Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19226586Sdim#include "llvm/ADT/FoldingSet.h" 20226586Sdim 21226586Sdimnamespace clang { 22226586Sdim 23226586Sdimnamespace ento { 24226586Sdim 25226586Sdimclass BugReport; 26226586Sdimclass BugReporterContext; 27226586Sdimclass ExplodedNode; 28226586Sdimclass MemRegion; 29226586Sdimclass PathDiagnosticPiece; 30226586Sdim 31234353Sdim/// \brief BugReporterVisitors are used to add custom diagnostics along a path. 32234353Sdim/// 33234353Sdim/// Custom visitors should subclass the BugReporterVisitorImpl class for a 34234353Sdim/// default implementation of the clone() method. 35234353Sdim/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 36234353Sdim/// default implementation of clone() will NOT do the right thing, and you 37234353Sdim/// will have to provide your own implementation.) 38226586Sdimclass BugReporterVisitor : public llvm::FoldingSetNode { 39226586Sdimpublic: 40226586Sdim virtual ~BugReporterVisitor(); 41226586Sdim 42234353Sdim /// \brief Returns a copy of this BugReporter. 43234353Sdim /// 44234353Sdim /// Custom BugReporterVisitors should not override this method directly. 45234353Sdim /// Instead, they should inherit from BugReporterVisitorImpl and provide 46234353Sdim /// a protected or public copy constructor. 47234353Sdim /// 48234353Sdim /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 49234353Sdim /// default implementation of clone() will NOT do the right thing, and you 50234353Sdim /// will have to provide your own implementation.) 51234353Sdim virtual BugReporterVisitor *clone() const = 0; 52234353Sdim 53226586Sdim /// \brief Return a diagnostic piece which should be associated with the 54226586Sdim /// given node. 55226586Sdim /// 56226586Sdim /// The last parameter can be used to register a new visitor with the given 57226586Sdim /// BugReport while processing a node. 58249423Sdim virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, 59249423Sdim const ExplodedNode *Pred, 60226586Sdim BugReporterContext &BRC, 61226586Sdim BugReport &BR) = 0; 62226586Sdim 63226586Sdim /// \brief Provide custom definition for the final diagnostic piece on the 64226586Sdim /// path - the piece, which is displayed before the path is expanded. 65226586Sdim /// 66226586Sdim /// If returns NULL the default implementation will be used. 67226586Sdim /// Also note that at most one visitor of a BugReport should generate a 68226586Sdim /// non-NULL end of path diagnostic piece. 69226586Sdim virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, 70226586Sdim const ExplodedNode *N, 71226586Sdim BugReport &BR); 72226586Sdim 73226586Sdim virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; 74226586Sdim 75226586Sdim /// \brief Generates the default final diagnostic piece. 76226586Sdim static PathDiagnosticPiece *getDefaultEndPath(BugReporterContext &BRC, 77226586Sdim const ExplodedNode *N, 78226586Sdim BugReport &BR); 79226586Sdim 80226586Sdim}; 81226586Sdim 82234353Sdim/// This class provides a convenience implementation for clone() using the 83234353Sdim/// Curiously-Recurring Template Pattern. If you are implementing a custom 84234353Sdim/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public 85234353Sdim/// or protected copy constructor. 86234353Sdim/// 87234353Sdim/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the 88234353Sdim/// default implementation of clone() will NOT do the right thing, and you 89234353Sdim/// will have to provide your own implementation.) 90234353Sdimtemplate <class DERIVED> 91234353Sdimclass BugReporterVisitorImpl : public BugReporterVisitor { 92234353Sdim virtual BugReporterVisitor *clone() const { 93234353Sdim return new DERIVED(*static_cast<const DERIVED *>(this)); 94234353Sdim } 95234353Sdim}; 96234353Sdim 97234353Sdimclass FindLastStoreBRVisitor 98234353Sdim : public BugReporterVisitorImpl<FindLastStoreBRVisitor> 99234353Sdim{ 100226586Sdim const MemRegion *R; 101226586Sdim SVal V; 102249423Sdim bool Satisfied; 103226586Sdim 104249423Sdim /// If the visitor is tracking the value directly responsible for the 105249423Sdim /// bug, we are going to employ false positive suppression. 106249423Sdim bool EnableNullFPSuppression; 107249423Sdim 108226586Sdimpublic: 109226586Sdim /// Creates a visitor for every VarDecl inside a Stmt and registers it with 110226586Sdim /// the BugReport. 111249423Sdim static void registerStatementVarDecls(BugReport &BR, const Stmt *S, 112249423Sdim bool EnableNullFPSuppression); 113226586Sdim 114249423Sdim FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R, 115249423Sdim bool InEnableNullFPSuppression) 116249423Sdim : R(R), 117249423Sdim V(V), 118249423Sdim Satisfied(false), 119249423Sdim EnableNullFPSuppression(InEnableNullFPSuppression) {} 120226586Sdim 121226586Sdim void Profile(llvm::FoldingSetNodeID &ID) const; 122226586Sdim 123226586Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 124226586Sdim const ExplodedNode *PrevN, 125226586Sdim BugReporterContext &BRC, 126226586Sdim BugReport &BR); 127226586Sdim}; 128226586Sdim 129234353Sdimclass TrackConstraintBRVisitor 130234353Sdim : public BugReporterVisitorImpl<TrackConstraintBRVisitor> 131234353Sdim{ 132226586Sdim DefinedSVal Constraint; 133249423Sdim bool Assumption; 134249423Sdim bool IsSatisfied; 135249423Sdim bool IsZeroCheck; 136226586Sdim 137251662Sdim /// We should start tracking from the last node along the path in which the 138251662Sdim /// value is constrained. 139251662Sdim bool IsTrackingTurnedOn; 140251662Sdim 141226586Sdimpublic: 142226586Sdim TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) 143249423Sdim : Constraint(constraint), Assumption(assumption), IsSatisfied(false), 144251662Sdim IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), 145251662Sdim IsTrackingTurnedOn(false) {} 146226586Sdim 147226586Sdim void Profile(llvm::FoldingSetNodeID &ID) const; 148226586Sdim 149243830Sdim /// Return the tag associated with this visitor. This tag will be used 150243830Sdim /// to make all PathDiagnosticPieces created by this visitor. 151243830Sdim static const char *getTag(); 152243830Sdim 153226586Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 154226586Sdim const ExplodedNode *PrevN, 155226586Sdim BugReporterContext &BRC, 156226586Sdim BugReport &BR); 157249423Sdim 158249423Sdimprivate: 159249423Sdim /// Checks if the constraint is valid in the current state. 160249423Sdim bool isUnderconstrained(const ExplodedNode *N) const; 161249423Sdim 162226586Sdim}; 163226586Sdim 164249423Sdim/// \class NilReceiverBRVisitor 165249423Sdim/// \brief Prints path notes when a message is sent to a nil receiver. 166234353Sdimclass NilReceiverBRVisitor 167249423Sdim : public BugReporterVisitorImpl<NilReceiverBRVisitor> { 168226586Sdimpublic: 169249423Sdim 170226586Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 171226586Sdim static int x = 0; 172226586Sdim ID.AddPointer(&x); 173226586Sdim } 174226586Sdim 175226586Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 176226586Sdim const ExplodedNode *PrevN, 177226586Sdim BugReporterContext &BRC, 178226586Sdim BugReport &BR); 179249423Sdim 180249423Sdim /// If the statement is a message send expression with nil receiver, returns 181249423Sdim /// the receiver expression. Returns NULL otherwise. 182249423Sdim static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N); 183226586Sdim}; 184226586Sdim 185226586Sdim/// Visitor that tries to report interesting diagnostics from conditions. 186234353Sdimclass ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { 187226586Sdimpublic: 188226586Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 189226586Sdim static int x = 0; 190226586Sdim ID.AddPointer(&x); 191226586Sdim } 192226586Sdim 193243830Sdim /// Return the tag associated with this visitor. This tag will be used 194243830Sdim /// to make all PathDiagnosticPieces created by this visitor. 195243830Sdim static const char *getTag(); 196234353Sdim 197226586Sdim virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 198226586Sdim const ExplodedNode *Prev, 199226586Sdim BugReporterContext &BRC, 200226586Sdim BugReport &BR); 201226586Sdim 202234353Sdim PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, 203234353Sdim const ExplodedNode *Prev, 204234353Sdim BugReporterContext &BRC, 205234353Sdim BugReport &BR); 206234353Sdim 207226586Sdim PathDiagnosticPiece *VisitTerminator(const Stmt *Term, 208226586Sdim const ExplodedNode *N, 209226586Sdim const CFGBlock *srcBlk, 210226586Sdim const CFGBlock *dstBlk, 211234353Sdim BugReport &R, 212226586Sdim BugReporterContext &BRC); 213226586Sdim 214226586Sdim PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 215226586Sdim bool tookTrue, 216226586Sdim BugReporterContext &BRC, 217234353Sdim BugReport &R, 218234353Sdim const ExplodedNode *N); 219226586Sdim 220226586Sdim PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 221226586Sdim const DeclRefExpr *DR, 222226586Sdim const bool tookTrue, 223226586Sdim BugReporterContext &BRC, 224234353Sdim BugReport &R, 225234353Sdim const ExplodedNode *N); 226226586Sdim 227226586Sdim PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 228226586Sdim const BinaryOperator *BExpr, 229226586Sdim const bool tookTrue, 230226586Sdim BugReporterContext &BRC, 231234353Sdim BugReport &R, 232234353Sdim const ExplodedNode *N); 233234353Sdim 234234353Sdim PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString, 235234353Sdim const Expr *CondVarExpr, 236234353Sdim const bool tookTrue, 237234353Sdim BugReporterContext &BRC, 238234353Sdim BugReport &R, 239234353Sdim const ExplodedNode *N); 240226586Sdim 241226586Sdim bool patternMatch(const Expr *Ex, 242249423Sdim raw_ostream &Out, 243234353Sdim BugReporterContext &BRC, 244234353Sdim BugReport &R, 245234353Sdim const ExplodedNode *N, 246249423Sdim Optional<bool> &prunable); 247226586Sdim}; 248243830Sdim 249249423Sdim/// \brief Suppress reports that might lead to known false positives. 250249423Sdim/// 251249423Sdim/// Currently this suppresses reports based on locations of bugs. 252249423Sdimclass LikelyFalsePositiveSuppressionBRVisitor 253249423Sdim : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> { 254249423Sdimpublic: 255249423Sdim static void *getTag() { 256249423Sdim static int Tag = 0; 257249423Sdim return static_cast<void *>(&Tag); 258249423Sdim } 259249423Sdim 260249423Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 261249423Sdim ID.AddPointer(getTag()); 262249423Sdim } 263249423Sdim 264249423Sdim virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 265249423Sdim const ExplodedNode *Prev, 266249423Sdim BugReporterContext &BRC, 267249423Sdim BugReport &BR) { 268249423Sdim return 0; 269249423Sdim } 270249423Sdim 271249423Sdim virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, 272249423Sdim const ExplodedNode *N, 273249423Sdim BugReport &BR); 274249423Sdim}; 275249423Sdim 276243830Sdim/// \brief When a region containing undefined value or '0' value is passed 277243830Sdim/// as an argument in a call, marks the call as interesting. 278243830Sdim/// 279243830Sdim/// As a result, BugReporter will not prune the path through the function even 280243830Sdim/// if the region's contents are not modified/accessed by the call. 281243830Sdimclass UndefOrNullArgVisitor 282243830Sdim : public BugReporterVisitorImpl<UndefOrNullArgVisitor> { 283243830Sdim 284243830Sdim /// The interesting memory region this visitor is tracking. 285243830Sdim const MemRegion *R; 286243830Sdim 287243830Sdimpublic: 288243830Sdim UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {} 289243830Sdim 290243830Sdim virtual void Profile(llvm::FoldingSetNodeID &ID) const { 291243830Sdim static int Tag = 0; 292243830Sdim ID.AddPointer(&Tag); 293243830Sdim ID.AddPointer(R); 294243830Sdim } 295243830Sdim 296243830Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 297243830Sdim const ExplodedNode *PrevN, 298243830Sdim BugReporterContext &BRC, 299243830Sdim BugReport &BR); 300243830Sdim}; 301243830Sdim 302249423Sdimclass SuppressInlineDefensiveChecksVisitor 303249423Sdim: public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> 304249423Sdim{ 305249423Sdim /// The symbolic value for which we are tracking constraints. 306249423Sdim /// This value is constrained to null in the end of path. 307249423Sdim DefinedSVal V; 308249423Sdim 309249423Sdim /// Track if we found the node where the constraint was first added. 310249423Sdim bool IsSatisfied; 311249423Sdim 312249423Sdim /// Since the visitors can be registered on nodes previous to the last 313249423Sdim /// node in the BugReport, but the path traversal always starts with the last 314249423Sdim /// node, the visitor invariant (that we start with a node in which V is null) 315249423Sdim /// might not hold when node visitation starts. We are going to start tracking 316249423Sdim /// from the last node in which the value is null. 317249423Sdim bool IsTrackingTurnedOn; 318249423Sdim 319249423Sdimpublic: 320249423Sdim SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); 321249423Sdim 322249423Sdim void Profile(llvm::FoldingSetNodeID &ID) const; 323249423Sdim 324249423Sdim /// Return the tag associated with this visitor. This tag will be used 325249423Sdim /// to make all PathDiagnosticPieces created by this visitor. 326249423Sdim static const char *getTag(); 327249423Sdim 328249423Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, 329249423Sdim const ExplodedNode *Pred, 330249423Sdim BugReporterContext &BRC, 331249423Sdim BugReport &BR); 332249423Sdim}; 333249423Sdim 334226586Sdimnamespace bugreporter { 335226586Sdim 336243830Sdim/// Attempts to add visitors to trace a null or undefined value back to its 337243830Sdim/// point of origin, whether it is a symbol constrained to null or an explicit 338243830Sdim/// assignment. 339243830Sdim/// 340243830Sdim/// \param N A node "downstream" from the evaluation of the statement. 341243830Sdim/// \param S The statement whose value is null or undefined. 342243830Sdim/// \param R The bug report to which visitors should be attached. 343243830Sdim/// \param IsArg Whether the statement is an argument to an inlined function. 344243830Sdim/// If this is the case, \p N \em must be the CallEnter node for 345243830Sdim/// the function. 346249423Sdim/// \param EnableNullFPSuppression Whether we should employ false positive 347249423Sdim/// suppression (inlined defensive checks, returned null). 348243830Sdim/// 349243830Sdim/// \return Whether or not the function was able to add visitors for this 350243830Sdim/// statement. Note that returning \c true does not actually imply 351243830Sdim/// that any visitors were added. 352243830Sdimbool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, 353249423Sdim bool IsArg = false, 354249423Sdim bool EnableNullFPSuppression = true); 355226586Sdim 356249423Sdimconst Expr *getDerefExpr(const Stmt *S); 357226586Sdimconst Stmt *GetDenomExpr(const ExplodedNode *N); 358226586Sdimconst Stmt *GetRetValExpr(const ExplodedNode *N); 359243830Sdimbool isDeclRefExprToReference(const Expr *E); 360226586Sdim 361243830Sdim 362226586Sdim} // end namespace clang 363226586Sdim} // end namespace ento 364226586Sdim} // end namespace bugreporter 365226586Sdim 366226586Sdim 367226586Sdim#endif //LLVM_CLANG_GR__BUGREPORTERVISITOR 368