BugReporterVisitors.cpp revision 20165e796c16311a83911db74c04d797e93471b2
17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// 27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// The LLVM Compiler Infrastructure 47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// License. See LICENSE.TXT for details. 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===// 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// This file defines a set of BugReporter "visitors" which can be used to 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// enhance the diagnostics reported for a bug. 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)//===----------------------------------------------------------------------===// 147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/AST/Expr.h" 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/AST/ExprObjC.h" 187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "llvm/ADT/SmallString.h" 24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using namespace clang; 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using namespace ento; 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)//===----------------------------------------------------------------------===// 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Utility functions. 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch//===----------------------------------------------------------------------===// 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) { 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Pattern match for a few useful cases (do something smarter later): 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // a[0], p->f, *p 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) while (true) { 387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) { 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) assert(B->isAssignmentOp()); 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) S = B->getLHS()->IgnoreParenCasts(); 417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) continue; 427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) { 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (U->getOpcode() == UO_Deref) 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return U->getSubExpr()->IgnoreParenCasts(); 467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return ME->getBase()->IgnoreParenCasts(); 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) { 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return AE->getBase(); 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return BE->getRHS(); 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return RS->getRetValue(); 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===// 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Definitions for bug reporter visitors. 757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===// 767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PathDiagnosticPiece* 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BugReporterVisitor::getEndPath(BugReporterContext &BRC, 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const ExplodedNode *EndPathNode, 807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BugReport &BR) { 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PathDiagnosticPiece* 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const ExplodedNode *EndPathNode, 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BugReport &BR) { 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PathDiagnosticLocation L = 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BugReport::ranges_iterator Beg, End; 927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) llvm::tie(Beg, End) = BR.getRanges(); 937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Only add the statement itself as a range if we didn't specify any 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // special ranges for this report. 967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, 977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BR.getDescription(), 987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Beg == End); 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (; Beg != End; ++Beg) 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) P->addRange(*Beg); 1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return P; 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static int tag = 0; 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ID.AddPointer(&tag); 1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ID.AddPointer(R); 1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ID.Add(V); 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const ExplodedNode *PrevN, 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BugReporterContext &BRC, 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BugReport &BR) { 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (satisfied) 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return NULL; 1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!StoreSite) { 1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Make sure the region is actually bound to value V here. 1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // This is necessary because the region may not actually be live at the 1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // report's error node. 1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (N->getState()->getSVal(R) != V) 1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const ExplodedNode *Node = N, *Last = N; 1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Now look for the store of V. 1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for ( ; Node ; Node = Node->getFirstPred()) { 1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const PostStmt *P = Node->getLocationAs<PostStmt>()) 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) 1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (DS->getSingleDecl() == VR->getDecl()) { 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Record the last seen initialization point. 1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Last = Node; 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 141c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 142c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Does the region still bind to value V? If not, we are done 143c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // looking for store sites. 144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (Node->getState()->getSVal(R) != V) 145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Last = Node; 1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 150 if (!Node) { 151 satisfied = true; 152 return NULL; 153 } 154 155 StoreSite = Last; 156 } 157 158 if (StoreSite != N) 159 return NULL; 160 161 satisfied = true; 162 SmallString<256> sbuf; 163 llvm::raw_svector_ostream os(sbuf); 164 165 if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { 166 if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { 167 168 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 169 os << "Variable '" << *VR->getDecl() << "' "; 170 } 171 else 172 return NULL; 173 174 if (isa<loc::ConcreteInt>(V)) { 175 bool b = false; 176 if (R->isBoundable()) { 177 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 178 if (TR->getValueType()->isObjCObjectPointerType()) { 179 os << "initialized to nil"; 180 b = true; 181 } 182 } 183 } 184 185 if (!b) 186 os << "initialized to a null pointer value"; 187 } 188 else if (isa<nonloc::ConcreteInt>(V)) { 189 os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); 190 } 191 else if (V.isUndef()) { 192 if (isa<VarRegion>(R)) { 193 const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 194 if (VD->getInit()) 195 os << "initialized to a garbage value"; 196 else 197 os << "declared without an initial value"; 198 } 199 } 200 } 201 } 202 203 if (os.str().empty()) { 204 if (isa<loc::ConcreteInt>(V)) { 205 bool b = false; 206 if (R->isBoundable()) { 207 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 208 if (TR->getValueType()->isObjCObjectPointerType()) { 209 os << "nil object reference stored to "; 210 b = true; 211 } 212 } 213 } 214 215 if (!b) 216 os << "Null pointer value stored to "; 217 } 218 else if (V.isUndef()) { 219 os << "Uninitialized value stored to "; 220 } 221 else if (isa<nonloc::ConcreteInt>(V)) { 222 os << "The value " << cast<nonloc::ConcreteInt>(V).getValue() 223 << " is assigned to "; 224 } 225 else 226 return NULL; 227 228 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 229 os << '\'' << *VR->getDecl() << '\''; 230 } 231 else 232 return NULL; 233 } 234 235 // Construct a new PathDiagnosticPiece. 236 ProgramPoint P = N->getLocation(); 237 PathDiagnosticLocation L = 238 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 239 if (!L.isValid()) 240 return NULL; 241 return new PathDiagnosticEventPiece(L, os.str()); 242} 243 244void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 245 static int tag = 0; 246 ID.AddPointer(&tag); 247 ID.AddBoolean(Assumption); 248 ID.Add(Constraint); 249} 250 251PathDiagnosticPiece * 252TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 253 const ExplodedNode *PrevN, 254 BugReporterContext &BRC, 255 BugReport &BR) { 256 if (isSatisfied) 257 return NULL; 258 259 // Check if in the previous state it was feasible for this constraint 260 // to *not* be true. 261 if (PrevN->getState()->assume(Constraint, !Assumption)) { 262 263 isSatisfied = true; 264 265 // As a sanity check, make sure that the negation of the constraint 266 // was infeasible in the current state. If it is feasible, we somehow 267 // missed the transition point. 268 if (N->getState()->assume(Constraint, !Assumption)) 269 return NULL; 270 271 // We found the transition point for the constraint. We now need to 272 // pretty-print the constraint. (work-in-progress) 273 std::string sbuf; 274 llvm::raw_string_ostream os(sbuf); 275 276 if (isa<Loc>(Constraint)) { 277 os << "Assuming pointer value is "; 278 os << (Assumption ? "non-null" : "null"); 279 } 280 281 if (os.str().empty()) 282 return NULL; 283 284 // Construct a new PathDiagnosticPiece. 285 ProgramPoint P = N->getLocation(); 286 PathDiagnosticLocation L = 287 PathDiagnosticLocation::create(P, BRC.getSourceManager()); 288 if (!L.isValid()) 289 return NULL; 290 return new PathDiagnosticEventPiece(L, os.str()); 291 } 292 293 return NULL; 294} 295 296BugReporterVisitor * 297bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, 298 const Stmt *S, 299 BugReport *report) { 300 if (!S || !N) 301 return 0; 302 303 ProgramStateManager &StateMgr = N->getState()->getStateManager(); 304 305 // Walk through nodes until we get one that matches the statement 306 // exactly. 307 while (N) { 308 const ProgramPoint &pp = N->getLocation(); 309 if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { 310 if (ps->getStmt() == S) 311 break; 312 } 313 N = N->getFirstPred(); 314 } 315 316 if (!N) 317 return 0; 318 319 ProgramStateRef state = N->getState(); 320 321 // Walk through lvalue-to-rvalue conversions. 322 const Expr *Ex = dyn_cast<Expr>(S); 323 if (Ex) { 324 Ex = Ex->IgnoreParenLValueCasts(); 325 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 326 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 327 const VarRegion *R = 328 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 329 330 // What did we load? 331 SVal V = state->getRawSVal(loc::MemRegionVal(R)); 332 report->markInteresting(R); 333 report->markInteresting(V); 334 return new FindLastStoreBRVisitor(V, R); 335 } 336 } 337 } 338 339 SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 340 341 // Uncomment this to find cases where we aren't properly getting the 342 // base value that was dereferenced. 343 // assert(!V.isUnknownOrUndef()); 344 345 // Is it a symbolic value? 346 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) { 347 const SubRegion *R = cast<SubRegion>(L->getRegion()); 348 while (R && !isa<SymbolicRegion>(R)) { 349 R = dyn_cast<SubRegion>(R->getSuperRegion()); 350 } 351 352 if (R) { 353 report->markInteresting(R); 354 return new TrackConstraintBRVisitor(loc::MemRegionVal(R), false); 355 } 356 } 357 358 return 0; 359} 360 361BugReporterVisitor * 362FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N, 363 const MemRegion *R) { 364 assert(R && "The memory region is null."); 365 366 ProgramStateRef state = N->getState(); 367 SVal V = state->getSVal(R); 368 if (V.isUnknown()) 369 return 0; 370 371 return new FindLastStoreBRVisitor(V, R); 372} 373 374 375PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 376 const ExplodedNode *PrevN, 377 BugReporterContext &BRC, 378 BugReport &BR) { 379 const PostStmt *P = N->getLocationAs<PostStmt>(); 380 if (!P) 381 return 0; 382 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 383 if (!ME) 384 return 0; 385 const Expr *Receiver = ME->getInstanceReceiver(); 386 if (!Receiver) 387 return 0; 388 ProgramStateRef state = N->getState(); 389 const SVal &V = state->getSVal(Receiver, N->getLocationContext()); 390 const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); 391 if (!DV) 392 return 0; 393 state = state->assume(*DV, true); 394 if (state) 395 return 0; 396 397 // The receiver was nil, and hence the method was skipped. 398 // Register a BugReporterVisitor to issue a message telling us how 399 // the receiver was null. 400 BR.addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Receiver, &BR)); 401 // Issue a message saying that the method was skipped. 402 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 403 N->getLocationContext()); 404 return new PathDiagnosticEventPiece(L, "No method is called " 405 "because the receiver is nil"); 406} 407 408// Registers every VarDecl inside a Stmt with a last store visitor. 409void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 410 const Stmt *S) { 411 const ExplodedNode *N = BR.getErrorNode(); 412 std::deque<const Stmt *> WorkList; 413 WorkList.push_back(S); 414 415 while (!WorkList.empty()) { 416 const Stmt *Head = WorkList.front(); 417 WorkList.pop_front(); 418 419 ProgramStateRef state = N->getState(); 420 ProgramStateManager &StateMgr = state->getStateManager(); 421 422 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 423 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 424 const VarRegion *R = 425 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 426 427 // What did we load? 428 SVal V = state->getSVal(S, N->getLocationContext()); 429 430 if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { 431 // Register a new visitor with the BugReport. 432 BR.addVisitor(new FindLastStoreBRVisitor(V, R)); 433 } 434 } 435 } 436 437 for (Stmt::const_child_iterator I = Head->child_begin(); 438 I != Head->child_end(); ++I) 439 WorkList.push_back(*I); 440 } 441} 442 443//===----------------------------------------------------------------------===// 444// Visitor that tries to report interesting diagnostics from conditions. 445//===----------------------------------------------------------------------===// 446PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 447 const ExplodedNode *Prev, 448 BugReporterContext &BRC, 449 BugReport &BR) { 450 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR); 451 if (PathDiagnosticEventPiece *ev = 452 dyn_cast_or_null<PathDiagnosticEventPiece>(piece)) 453 ev->setPrunable(true, /* override */ false); 454 return piece; 455} 456 457PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 458 const ExplodedNode *Prev, 459 BugReporterContext &BRC, 460 BugReport &BR) { 461 462 const ProgramPoint &progPoint = N->getLocation(); 463 464 ProgramStateRef CurrentState = N->getState(); 465 ProgramStateRef PrevState = Prev->getState(); 466 467 // Compare the GDMs of the state, because that is where constraints 468 // are managed. Note that ensure that we only look at nodes that 469 // were generated by the analyzer engine proper, not checkers. 470 if (CurrentState->getGDM().getRoot() == 471 PrevState->getGDM().getRoot()) 472 return 0; 473 474 // If an assumption was made on a branch, it should be caught 475 // here by looking at the state transition. 476 if (const BlockEdge *BE = dyn_cast<BlockEdge>(&progPoint)) { 477 const CFGBlock *srcBlk = BE->getSrc(); 478 if (const Stmt *term = srcBlk->getTerminator()) 479 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); 480 return 0; 481 } 482 483 if (const PostStmt *PS = dyn_cast<PostStmt>(&progPoint)) { 484 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 485 // violation. 486 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 487 cast<GRBugReporter>(BRC.getBugReporter()). 488 getEngine().getEagerlyAssumeTags(); 489 490 const ProgramPointTag *tag = PS->getTag(); 491 if (tag == tags.first) 492 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 493 BRC, BR, N); 494 if (tag == tags.second) 495 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 496 BRC, BR, N); 497 498 return 0; 499 } 500 501 return 0; 502} 503 504PathDiagnosticPiece * 505ConditionBRVisitor::VisitTerminator(const Stmt *Term, 506 const ExplodedNode *N, 507 const CFGBlock *srcBlk, 508 const CFGBlock *dstBlk, 509 BugReport &R, 510 BugReporterContext &BRC) { 511 const Expr *Cond = 0; 512 513 switch (Term->getStmtClass()) { 514 default: 515 return 0; 516 case Stmt::IfStmtClass: 517 Cond = cast<IfStmt>(Term)->getCond(); 518 break; 519 case Stmt::ConditionalOperatorClass: 520 Cond = cast<ConditionalOperator>(Term)->getCond(); 521 break; 522 } 523 524 assert(Cond); 525 assert(srcBlk->succ_size() == 2); 526 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 527 return VisitTrueTest(Cond->IgnoreParenNoopCasts(BRC.getASTContext()), 528 tookTrue, BRC, R, N); 529} 530 531PathDiagnosticPiece * 532ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 533 bool tookTrue, 534 BugReporterContext &BRC, 535 BugReport &R, 536 const ExplodedNode *N) { 537 538 const Expr *Ex = Cond; 539 540 while (true) { 541 Ex = Ex->IgnoreParens(); 542 switch (Ex->getStmtClass()) { 543 default: 544 return 0; 545 case Stmt::BinaryOperatorClass: 546 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, 547 R, N); 548 case Stmt::DeclRefExprClass: 549 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, 550 R, N); 551 case Stmt::UnaryOperatorClass: { 552 const UnaryOperator *UO = cast<UnaryOperator>(Ex); 553 if (UO->getOpcode() == UO_LNot) { 554 tookTrue = !tookTrue; 555 Ex = UO->getSubExpr()->IgnoreParenNoopCasts(BRC.getASTContext()); 556 continue; 557 } 558 return 0; 559 } 560 } 561 } 562} 563 564bool ConditionBRVisitor::patternMatch(const Expr *Ex, llvm::raw_ostream &Out, 565 BugReporterContext &BRC, 566 BugReport &report, 567 const ExplodedNode *N, 568 llvm::Optional<bool> &prunable) { 569 const Expr *OriginalExpr = Ex; 570 Ex = Ex->IgnoreParenCasts(); 571 572 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 573 const bool quotes = isa<VarDecl>(DR->getDecl()); 574 if (quotes) { 575 Out << '\''; 576 const LocationContext *LCtx = N->getLocationContext(); 577 const ProgramState *state = N->getState().getPtr(); 578 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 579 LCtx).getAsRegion()) { 580 if (report.isInteresting(R)) 581 prunable = false; 582 else { 583 const ProgramState *state = N->getState().getPtr(); 584 SVal V = state->getSVal(R); 585 if (report.isInteresting(V)) 586 prunable = false; 587 } 588 } 589 } 590 Out << DR->getDecl()->getDeclName().getAsString(); 591 if (quotes) 592 Out << '\''; 593 return quotes; 594 } 595 596 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 597 QualType OriginalTy = OriginalExpr->getType(); 598 if (OriginalTy->isPointerType()) { 599 if (IL->getValue() == 0) { 600 Out << "null"; 601 return false; 602 } 603 } 604 else if (OriginalTy->isObjCObjectPointerType()) { 605 if (IL->getValue() == 0) { 606 Out << "nil"; 607 return false; 608 } 609 } 610 611 Out << IL->getValue(); 612 return false; 613 } 614 615 return false; 616} 617 618PathDiagnosticPiece * 619ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 620 const BinaryOperator *BExpr, 621 const bool tookTrue, 622 BugReporterContext &BRC, 623 BugReport &R, 624 const ExplodedNode *N) { 625 626 bool shouldInvert = false; 627 llvm::Optional<bool> shouldPrune; 628 629 SmallString<128> LhsString, RhsString; 630 { 631 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 632 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, 633 shouldPrune); 634 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, 635 shouldPrune); 636 637 shouldInvert = !isVarLHS && isVarRHS; 638 } 639 640 BinaryOperator::Opcode Op = BExpr->getOpcode(); 641 642 if (BinaryOperator::isAssignmentOp(Op)) { 643 // For assignment operators, all that we care about is that the LHS 644 // evaluates to "true" or "false". 645 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 646 BRC, R, N); 647 } 648 649 // For non-assignment operations, we require that we can understand 650 // both the LHS and RHS. 651 if (LhsString.empty() || RhsString.empty()) 652 return 0; 653 654 // Should we invert the strings if the LHS is not a variable name? 655 SmallString<256> buf; 656 llvm::raw_svector_ostream Out(buf); 657 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 658 659 // Do we need to invert the opcode? 660 if (shouldInvert) 661 switch (Op) { 662 default: break; 663 case BO_LT: Op = BO_GT; break; 664 case BO_GT: Op = BO_LT; break; 665 case BO_LE: Op = BO_GE; break; 666 case BO_GE: Op = BO_LE; break; 667 } 668 669 if (!tookTrue) 670 switch (Op) { 671 case BO_EQ: Op = BO_NE; break; 672 case BO_NE: Op = BO_EQ; break; 673 case BO_LT: Op = BO_GE; break; 674 case BO_GT: Op = BO_LE; break; 675 case BO_LE: Op = BO_GT; break; 676 case BO_GE: Op = BO_LT; break; 677 default: 678 return 0; 679 } 680 681 switch (Op) { 682 case BO_EQ: 683 Out << "equal to "; 684 break; 685 case BO_NE: 686 Out << "not equal to "; 687 break; 688 default: 689 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 690 break; 691 } 692 693 Out << (shouldInvert ? LhsString : RhsString); 694 const LocationContext *LCtx = N->getLocationContext(); 695 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 696 PathDiagnosticEventPiece *event = 697 new PathDiagnosticEventPiece(Loc, Out.str()); 698 if (shouldPrune.hasValue()) 699 event->setPrunable(shouldPrune.getValue()); 700 return event; 701} 702 703PathDiagnosticPiece * 704ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 705 const Expr *CondVarExpr, 706 const bool tookTrue, 707 BugReporterContext &BRC, 708 BugReport &report, 709 const ExplodedNode *N) { 710 SmallString<256> buf; 711 llvm::raw_svector_ostream Out(buf); 712 Out << "Assuming " << LhsString << " is "; 713 714 QualType Ty = CondVarExpr->getType(); 715 716 if (Ty->isPointerType()) 717 Out << (tookTrue ? "not null" : "null"); 718 else if (Ty->isObjCObjectPointerType()) 719 Out << (tookTrue ? "not nil" : "nil"); 720 else if (Ty->isBooleanType()) 721 Out << (tookTrue ? "true" : "false"); 722 else if (Ty->isIntegerType()) 723 Out << (tookTrue ? "non-zero" : "zero"); 724 else 725 return 0; 726 727 const LocationContext *LCtx = N->getLocationContext(); 728 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 729 PathDiagnosticEventPiece *event = 730 new PathDiagnosticEventPiece(Loc, Out.str()); 731 732 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { 733 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 734 const ProgramState *state = N->getState().getPtr(); 735 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 736 if (report.isInteresting(R)) 737 event->setPrunable(false); 738 } 739 } 740 } 741 742 return event; 743} 744 745PathDiagnosticPiece * 746ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 747 const DeclRefExpr *DR, 748 const bool tookTrue, 749 BugReporterContext &BRC, 750 BugReport &report, 751 const ExplodedNode *N) { 752 753 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 754 if (!VD) 755 return 0; 756 757 SmallString<256> Buf; 758 llvm::raw_svector_ostream Out(Buf); 759 760 Out << "Assuming '"; 761 VD->getDeclName().printName(Out); 762 Out << "' is "; 763 764 QualType VDTy = VD->getType(); 765 766 if (VDTy->isPointerType()) 767 Out << (tookTrue ? "non-null" : "null"); 768 else if (VDTy->isObjCObjectPointerType()) 769 Out << (tookTrue ? "non-nil" : "nil"); 770 else if (VDTy->isScalarType()) 771 Out << (tookTrue ? "not equal to 0" : "0"); 772 else 773 return 0; 774 775 const LocationContext *LCtx = N->getLocationContext(); 776 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 777 PathDiagnosticEventPiece *event = 778 new PathDiagnosticEventPiece(Loc, Out.str()); 779 780 const ProgramState *state = N->getState().getPtr(); 781 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 782 if (report.isInteresting(R)) 783 event->setPrunable(false); 784 else { 785 SVal V = state->getSVal(R); 786 if (report.isInteresting(V)) 787 event->setPrunable(false); 788 } 789 } 790 return event; 791} 792 793