BugReporterVisitors.cpp revision 3b9e8e40dab1295de4f14d9cf8d24c22422a42d2
1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// The LLVM Compiler Infrastructure 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// License. See LICENSE.TXT for details. 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// This file defines a set of BugReporter "visitors" which can be used to 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// enhance the diagnostics reported for a bug. 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/AST/Expr.h" 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/AST/ExprObjC.h" 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)using namespace clang; 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)using namespace ento; 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Utility functions. 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) { 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Pattern match for a few useful cases (do something smarter later): 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // a[0], p->f, *p 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) { 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U->getOpcode() == UO_Deref) 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return U->getSubExpr()->IgnoreParenCasts(); 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return ME->getBase()->IgnoreParenCasts(); 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) { 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return AE->getBase(); 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return BE->getRHS(); 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetCalleeExpr(const ExplodedNode *N) { 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Callee is checked as a PreVisit to the CallExpr. 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const CallExpr *CE = dyn_cast<CallExpr>(S)) 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return CE->getCallee(); 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return RS->getRetValue(); 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Definitions for bug reporter visitors. 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//===----------------------------------------------------------------------===// 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)namespace { 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class FindLastStoreBRVisitor : public BugReporterVisitor { 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const MemRegion *R; 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SVal V; 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bool satisfied; 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *StoreSite; 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public: 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) FindLastStoreBRVisitor(SVal v, const MemRegion *r) 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) : R(r), V(v), satisfied(false), StoreSite(0) {} 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) virtual void Profile(llvm::FoldingSetNodeID &ID) const { 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) static int tag = 0; 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.AddPointer(&tag); 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.AddPointer(R); 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.Add(V); 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *PrevN, 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BugReporterContext &BRC) { 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (satisfied) 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!StoreSite) { 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *Node = N, *Last = NULL; 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for ( ; Node ; Last = Node, Node = Node->getFirstPred()) { 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const PostStmt *P = Node->getLocationAs<PostStmt>()) 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (DS->getSingleDecl() == VR->getDecl()) { 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Last = Node; 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (Node->getState()->getSVal(R) != V) 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!Node || !Last) { 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) satisfied = true; 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) StoreSite = Last; 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (StoreSite != N) 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) satisfied = true; 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) llvm::SmallString<256> sbuf; 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) llvm::raw_svector_ostream os(sbuf); 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "Variable '" << VR->getDecl() << "' "; 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isa<loc::ConcreteInt>(V)) { 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bool b = false; 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (R->isBoundable()) { 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (TR->getValueType()->isObjCObjectPointerType()) { 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "initialized to nil"; 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) b = true; 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!b) 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "initialized to a null pointer value"; 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (isa<nonloc::ConcreteInt>(V)) { 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (V.isUndef()) { 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isa<VarRegion>(R)) { 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (VD->getInit()) 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "initialized to a garbage value"; 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "declared without an initial value"; 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (os.str().empty()) { 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isa<loc::ConcreteInt>(V)) { 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bool b = false; 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (R->isBoundable()) { 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (TR->getValueType()->isObjCObjectPointerType()) { 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "nil object reference stored to "; 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) b = true; 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!b) 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "Null pointer value stored to "; 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (V.isUndef()) { 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "Uninitialized value stored to "; 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (isa<nonloc::ConcreteInt>(V)) { 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) << " is assigned to "; 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << '\'' << VR->getDecl() << '\''; 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // FIXME: Refactor this into BugReporterContext. 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = 0; 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ProgramPoint P = N->getLocation(); 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const CFGBlock *BSrc = BE->getSrc(); 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) S = BSrc->getTerminatorCondition(); 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) { 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) S = PS->getStmt(); 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!S) 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Construct a new PathDiagnosticPiece. 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticLocation L(S, BRC.getSourceManager()); 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return new PathDiagnosticEventPiece(L, os.str()); 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}; 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void registerFindLastStore(BugReporterContext &BRC, const MemRegion *R, 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SVal V) { 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BRC.addVisitor(new FindLastStoreBRVisitor(V, R)); 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class TrackConstraintBRVisitor : public BugReporterVisitor { 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DefinedSVal Constraint; 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const bool Assumption; 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bool isSatisfied; 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public: 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) : Constraint(constraint), Assumption(assumption), isSatisfied(false) {} 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void Profile(llvm::FoldingSetNodeID &ID) const { 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) static int tag = 0; 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.AddPointer(&tag); 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.AddBoolean(Assumption); 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.Add(Constraint); 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *PrevN, 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BugReporterContext &BRC) { 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isSatisfied) 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Check if in the previous state it was feasible for this constraint 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // to *not* be true. 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (PrevN->getState()->assume(Constraint, !Assumption)) { 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) isSatisfied = true; 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // As a sanity check, make sure that the negation of the constraint 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // was infeasible in the current state. If it is feasible, we somehow 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // missed the transition point. 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (N->getState()->assume(Constraint, !Assumption)) 260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We found the transition point for the constraint. We now need to 263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // pretty-print the constraint. (work-in-progress) 264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) std::string sbuf; 265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) llvm::raw_string_ostream os(sbuf); 266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isa<Loc>(Constraint)) { 268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << "Assuming pointer value is "; 269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) os << (Assumption ? "non-null" : "null"); 270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (os.str().empty()) 273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // FIXME: Refactor this into BugReporterContext. 276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = 0; 277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ProgramPoint P = N->getLocation(); 278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const CFGBlock *BSrc = BE->getSrc(); 281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) S = BSrc->getTerminatorCondition(); 282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) { 284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) S = PS->getStmt(); 285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!S) 288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Construct a new PathDiagnosticPiece. 291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticLocation L(S, BRC.getSourceManager()); 292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return new PathDiagnosticEventPiece(L, os.str()); 293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}; 298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} // end anonymous namespace 299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void registerTrackConstraint(BugReporterContext &BRC, 301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DefinedSVal Constraint, 302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bool Assumption) { 303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BRC.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption)); 304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerTrackNullOrUndefValue(BugReporterContext &BRC, 307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *data, 308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *N) { 309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = static_cast<const Stmt*>(data); 311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!S) 313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ProgramStateManager &StateMgr = BRC.getStateManager(); 316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Walk through nodes until we get one that matches the statement 318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // exactly. 319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (N) { 320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ProgramPoint &pp = N->getLocation(); 321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { 322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (ps->getStmt() == S) 323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) N = *N->pred_begin(); 326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!N) 329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ProgramState *state = N->getState(); 332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Walk through lvalue-to-rvalue conversions. 334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S)) { 335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const VarRegion *R = 337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // What did we load? 340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SVal V = state->getSVal(loc::MemRegionVal(R)); 341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V) 343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) || V.isUndef()) { 344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ::registerFindLastStore(BRC, R, V); 345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SVal V = state->getSValAsScalarOrLoc(S); 350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Uncomment this to find cases where we aren't properly getting the 352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // base value that was dereferenced. 353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(!V.isUnknownOrUndef()); 354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Is it a symbolic value? 356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) { 357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const SubRegion *R = cast<SubRegion>(L->getRegion()); 358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (R && !isa<SymbolicRegion>(R)) { 359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) R = dyn_cast<SubRegion>(R->getSuperRegion()); 360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (R) { 363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) assert(isa<SymbolicRegion>(R)); 364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerTrackConstraint(BRC, loc::MemRegionVal(R), false); 365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerFindLastStore(BugReporterContext &BRC, 370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *data, 371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *N) { 372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const MemRegion *R = static_cast<const MemRegion*>(data); 374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!R) 376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ProgramState *state = N->getState(); 379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) SVal V = state->getSVal(R); 380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (V.isUnknown()) 382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BRC.addVisitor(new FindLastStoreBRVisitor(V, R)); 385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)namespace { 389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class NilReceiverVisitor : public BugReporterVisitor { 390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public: 391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) NilReceiverVisitor() {} 392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void Profile(llvm::FoldingSetNodeID &ID) const { 394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) static int x = 0; 395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID.AddPointer(&x); 396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *PrevN, 400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BugReporterContext &BRC) { 401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const PostStmt *P = N->getLocationAs<PostStmt>(); 403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!P) 404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!ME) 407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Expr *Receiver = ME->getInstanceReceiver(); 409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!Receiver) 410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ProgramState *state = N->getState(); 412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const SVal &V = state->getSVal(Receiver); 413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); 414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!DV) 415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) state = state->assume(*DV, true); 417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (state) 418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The receiver was nil, and hence the method was skipped. 421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Register a BugReporterVisitor to issue a message telling us how 422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // the receiver was null. 423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bugreporter::registerTrackNullOrUndefValue(BRC, Receiver, N); 424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Issue a message saying that the method was skipped. 425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PathDiagnosticLocation L(Receiver, BRC.getSourceManager()); 426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return new PathDiagnosticEventPiece(L, "No method actually called " 427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) "because the receiver is nil"); 428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}; 430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} // end anonymous namespace 431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) { 433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BRC.addVisitor(new NilReceiverVisitor()); 434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Registers every VarDecl inside a Stmt with a last store vistor. 437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC, 438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *stmt, 439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const ExplodedNode *N) { 440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const Stmt *S = static_cast<const Stmt *>(stmt); 441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) std::deque<const Stmt *> WorkList; 443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) WorkList.push_back(S); 445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (!WorkList.empty()) { 447 const Stmt *Head = WorkList.front(); 448 WorkList.pop_front(); 449 450 ProgramStateManager &StateMgr = BRC.getStateManager(); 451 const ProgramState *state = N->getState(); 452 453 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 454 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 455 const VarRegion *R = 456 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 457 458 // What did we load? 459 SVal V = state->getSVal(S); 460 461 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { 462 ::registerFindLastStore(BRC, R, V); 463 } 464 } 465 } 466 467 for (Stmt::const_child_iterator I = Head->child_begin(); 468 I != Head->child_end(); ++I) 469 WorkList.push_back(*I); 470 } 471} 472 473//===----------------------------------------------------------------------===// 474// Visitor that tries to report interesting diagnostics from conditions. 475//===----------------------------------------------------------------------===// 476 477namespace { 478class ConditionVisitor : public BugReporterVisitor { 479public: 480 void Profile(llvm::FoldingSetNodeID &ID) const { 481 static int x = 0; 482 ID.AddPointer(&x); 483 } 484 485 virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 486 const ExplodedNode *Prev, 487 BugReporterContext &BRC); 488 489 PathDiagnosticPiece *VisitTerminator(const Stmt *Term, 490 const ProgramState *CurrentState, 491 const ProgramState *PrevState, 492 const CFGBlock *srcBlk, 493 const CFGBlock *dstBlk, 494 BugReporterContext &BRC); 495 496 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 497 bool tookTrue, 498 BugReporterContext &BRC); 499 500 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 501 const DeclRefExpr *DR, 502 const bool tookTrue, 503 BugReporterContext &BRC); 504 505 PathDiagnosticPiece *VisitTrueTest(const Expr *Cond, 506 const BinaryOperator *BExpr, 507 const bool tookTrue, 508 BugReporterContext &BRC); 509 510 bool patternMatch(const Expr *Ex, 511 llvm::raw_ostream &Out, 512 BugReporterContext &BRC); 513}; 514} 515 516PathDiagnosticPiece *ConditionVisitor::VisitNode(const ExplodedNode *N, 517 const ExplodedNode *Prev, 518 BugReporterContext &BRC) { 519 520 const ProgramPoint &progPoint = N->getLocation(); 521 522 const ProgramState *CurrentState = N->getState(); 523 const ProgramState *PrevState = Prev->getState(); 524 525 // Compare the GDMs of the state, because that is where constraints 526 // are managed. Note that ensure that we only look at nodes that 527 // were generated by the analyzer engine proper, not checkers. 528 if (CurrentState->getGDM().getRoot() == 529 PrevState->getGDM().getRoot()) 530 return 0; 531 532 // If an assumption was made on a branch, it should be caught 533 // here by looking at the state transition. 534 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) { 535 const CFGBlock *srcBlk = BE->getSrc(); 536 if (const Stmt *term = srcBlk->getTerminator()) 537 return VisitTerminator(term, CurrentState, PrevState, 538 srcBlk, BE->getDst(), BRC); 539 return 0; 540 } 541 542 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) { 543 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 544 // violation. 545 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 546 cast<GRBugReporter>(BRC.getBugReporter()). 547 getEngine().getEagerlyAssumeTags(); 548 549 const ProgramPointTag *tag = PS->getTag(); 550 if (tag == tags.first) 551 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, BRC); 552 if (tag == tags.second) 553 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, BRC); 554 555 return 0; 556 } 557 558 return 0; 559} 560 561PathDiagnosticPiece * 562ConditionVisitor::VisitTerminator(const Stmt *Term, 563 const ProgramState *CurrentState, 564 const ProgramState *PrevState, 565 const CFGBlock *srcBlk, 566 const CFGBlock *dstBlk, 567 BugReporterContext &BRC) { 568 569 const Expr *Cond = 0; 570 571 switch (Term->getStmtClass()) { 572 default: 573 return 0; 574 case Stmt::IfStmtClass: 575 Cond = cast<IfStmt>(Term)->getCond(); 576 break; 577 case Stmt::ConditionalOperatorClass: 578 Cond = cast<ConditionalOperator>(Term)->getCond(); 579 break; 580 } 581 582 assert(Cond); 583 assert(srcBlk->succ_size() == 2); 584 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 585 return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()), 586 tookTrue, BRC); 587} 588 589PathDiagnosticPiece * 590ConditionVisitor::VisitTrueTest(const Expr *Cond, 591 bool tookTrue, 592 BugReporterContext &BRC) { 593 594 const Expr *Ex = Cond; 595 596 while (true) { 597 Ex = Ex->IgnoreParens(); 598 switch (Ex->getStmtClass()) { 599 default: 600 return 0; 601 case Stmt::BinaryOperatorClass: 602 return VisitTrueTest(Cond, cast<BinaryOperator>(Cond), tookTrue, BRC); 603 case Stmt::DeclRefExprClass: 604 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC); 605 case Stmt::UnaryOperatorClass: { 606 const UnaryOperator *UO = cast<UnaryOperator>(Ex); 607 if (UO->getOpcode() == UO_LNot) { 608 tookTrue = !tookTrue; 609 Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext()); 610 continue; 611 } 612 return 0; 613 } 614 } 615 } 616} 617 618bool ConditionVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out, 619 BugReporterContext &BRC) { 620 const Expr *OriginalExpr = Ex; 621 Ex = Ex->IgnoreParenCasts(); 622 623 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 624 const bool quotes = isa<VarDecl>(DR->getDecl()); 625 if (quotes) 626 Out << '\''; 627 Out << DR->getDecl()->getDeclName().getAsString(); 628 if (quotes) 629 Out << '\''; 630 return quotes; 631 } 632 633 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 634 QualType OriginalTy = OriginalExpr->getType(); 635 if (OriginalTy->isPointerType()) { 636 if (IL->getValue() == 0) { 637 Out << "null"; 638 return false; 639 } 640 } 641 else if (OriginalTy->isObjCObjectPointerType()) { 642 if (IL->getValue() == 0) { 643 Out << "nil"; 644 return false; 645 } 646 } 647 648 Out << IL->getValue(); 649 return false; 650 } 651 652 return false; 653} 654 655PathDiagnosticPiece * 656ConditionVisitor::VisitTrueTest(const Expr *Cond, 657 const BinaryOperator *BExpr, 658 const bool tookTrue, 659 BugReporterContext &BRC) { 660 661 bool shouldInvert = false; 662 663 llvm::SmallString<128> LhsString, RhsString; 664 { 665 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 666 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC); 667 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC); 668 669 shouldInvert = !isVarLHS && isVarRHS; 670 } 671 672 if (LhsString.empty() || RhsString.empty()) 673 return 0; 674 675 // Should we invert the strings if the LHS is not a variable name? 676 677 llvm::SmallString<256> buf; 678 llvm::raw_svector_ostream Out(buf); 679 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 680 681 // Do we need to invert the opcode? 682 BinaryOperator::Opcode Op = BExpr->getOpcode(); 683 684 if (shouldInvert) 685 switch (Op) { 686 default: break; 687 case BO_LT: Op = BO_GT; break; 688 case BO_GT: Op = BO_LT; break; 689 case BO_LE: Op = BO_GE; break; 690 case BO_GE: Op = BO_LE; break; 691 } 692 693 if (!tookTrue) 694 switch (Op) { 695 case BO_EQ: Op = BO_NE; break; 696 case BO_NE: Op = BO_EQ; break; 697 case BO_LT: Op = BO_GE; break; 698 case BO_GT: Op = BO_LE; break; 699 case BO_LE: Op = BO_GT; break; 700 case BO_GE: Op = BO_LT; break; 701 default: 702 return 0; 703 } 704 705 switch (BExpr->getOpcode()) { 706 case BO_EQ: 707 Out << "equal to "; 708 break; 709 case BO_NE: 710 Out << "not equal to "; 711 break; 712 default: 713 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 714 break; 715 } 716 717 Out << (shouldInvert ? LhsString : RhsString); 718 719 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager()); 720 return new PathDiagnosticEventPiece(Loc, Out.str()); 721} 722 723PathDiagnosticPiece * 724ConditionVisitor::VisitTrueTest(const Expr *Cond, 725 const DeclRefExpr *DR, 726 const bool tookTrue, 727 BugReporterContext &BRC) { 728 729 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 730 if (!VD) 731 return 0; 732 733 llvm::SmallString<256> Buf; 734 llvm::raw_svector_ostream Out(Buf); 735 736 Out << "Assuming '"; 737 VD->getDeclName().printName(Out); 738 Out << "' is "; 739 740 QualType VDTy = VD->getType(); 741 742 if (VDTy->isPointerType()) 743 Out << (tookTrue ? "non-null" : "null"); 744 else if (VDTy->isObjCObjectPointerType()) 745 Out << (tookTrue ? "non-nil" : "nil"); 746 else if (VDTy->isScalarType()) 747 Out << (tookTrue ? "not equal to 0" : "0"); 748 else 749 return 0; 750 751 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager()); 752 return new PathDiagnosticEventPiece(Loc, Out.str()); 753} 754 755void bugreporter::registerConditionVisitor(BugReporterContext &BRC) { 756 BRC.addVisitor(new ConditionVisitor()); 757} 758 759