BugReporterVisitors.cpp revision 9abf1b4577b75ffcc46afbdfb55de334f68f05c0
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// The LLVM Compiler Infrastructure 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// This file is distributed under the University of Illinois Open Source 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// License. See LICENSE.TXT for details. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com//===----------------------------------------------------------------------===// 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// This file defines a set of BugReporter "visitors" which can be used to 11309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org// enhance the diagnostics reported for a bug. 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===// 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 15bbe50131413098bffed9186660c41f047d881596bungeman@google.com#include "clang/AST/Expr.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/AST/ExprObjC.h" 1797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 188b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/ADT/SmallString.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/ADT/StringExtras.h" 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "llvm/Support/raw_ostream.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing namespace clang; 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comusing namespace ento; 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===// 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Utility functions. 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//===----------------------------------------------------------------------===// 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 346c14b43a840c791699747ba4cc0ed5abf2bda218reed@android.combool bugreporter::isDeclRefExprToReference(const Expr *E) { 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DRE->getDecl()->getType()->isReferenceType(); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 38309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org return false; 39309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org} 40309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org 417db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.comconst Expr *bugreporter::getDerefExpr(const Stmt *S) { 427db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // Pattern match for a few useful cases (do something smarter later): 437db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // a[0], p->f, *p 447db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com const Expr *E = dyn_cast<Expr>(S); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!E) 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com E = E->IgnoreParenCasts(); 4862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 4962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com while (true) { 5062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) { 5162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com assert(B->isAssignmentOp()); 5262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com E = B->getLHS()->IgnoreParenCasts(); 5362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com continue; 5462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 5562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) { 5662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (U->getOpcode() == UO_Deref) 5762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return U->getSubExpr()->IgnoreParenCasts(); 5862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 5962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { 6062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) { 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ME->getBase()->IgnoreParenCasts(); 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) { 65353482251e61971a8cf3a60bbb6910f482be634freed@google.com return IvarRef->getBase()->IgnoreParenCasts(); 66c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org } 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return AE->getBase(); 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 70583b18a20959c9ac360316a366f4ddd9598bdf52skia.committer@gmail.com break; 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 728b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org 73c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org return NULL; 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) 790da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com return BE->getRHS(); 8097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return NULL; 81a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com} 820da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com 83c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgconst Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { 84c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 85c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) 86c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org return RS->getRetValue(); 87c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org return NULL; 88c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org} 89a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 9097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com//===----------------------------------------------------------------------===// 91a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com// Definitions for bug reporter visitors. 92a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com//===----------------------------------------------------------------------===// 93a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 94a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comPathDiagnosticPiece* 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comBugReporterVisitor::getEndPath(BugReporterContext &BRC, 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ExplodedNode *EndPathNode, 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport &BR) { 9834abef14a637450743e1debccdcdb5bdc2e9ba01commit-bot@chromium.org return 0; 997db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com} 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comPathDiagnosticPiece* 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comBugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ExplodedNode *EndPathNode, 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport &BR) { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PathDiagnosticLocation L = 1067db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); 1077db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport::ranges_iterator Beg, End; 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com llvm::tie(Beg, End) = BR.getRanges(); 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Only add the statement itself as a range if we didn't specify any 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // special ranges for this report. 11382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, 11482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com BR.getDescription(), 11582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com Beg == End); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; Beg != End; ++Beg) 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com P->addRange(*Beg); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return P; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnamespace { 1241b27704eba15be4e9d1997faac42038493a30be5djsollen/// Emits an extra note at the return statement of an interesting stack frame. 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// The returned value is marked as an interesting value, and if it's null, 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// adds a visitor to track where it became null. 1281b27704eba15be4e9d1997faac42038493a30be5djsollen/// 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// This visitor is intended to be used when another visitor discovers that an 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// interesting value comes from an inlined function call. 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const StackFrameContext *StackFrame; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum { 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Initial, 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MaybeSuppress, 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Satisfied 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } Mode; 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ReturnVisitor(const StackFrameContext *Frame) 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : StackFrame(Frame), Mode(Initial) {} 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void *getTag() { 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int Tag = 0; 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return static_cast<void *>(&Tag); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void Profile(llvm::FoldingSetNodeID &ID) const { 149a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com ID.AddPointer(ReturnVisitor::getTag()); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ID.AddPointer(StackFrame); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// Adds a ReturnVisitor if the given statement represents a call that was 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// inlined. 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// This will search back through the ExplodedGraph, starting from the given 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// node, looking for when the given statement was processed. If it turns out 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// the statement is a call that was inlined, we add the visitor to the 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// bug report, so it can print a note later. 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S, 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport &BR) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!CallEvent::isCallStmt(S)) 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // First, find when we processed the statement. 1667767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org do { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>()) 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (CEE->getCalleeContext()->getCallSite() == S) 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>()) 171d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (SP->getStmt() == S) 17282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com break; 173b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com 1747767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org Node = Node->getFirstPred(); 175d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com } while (Node); 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Next, step over any post-statement checks. 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (Node && Node->getLocation().getAs<PostStmt>()) 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Node = Node->getFirstPred(); 1800abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 1810abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // Finally, see if we inlined the call. 182d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Node) { 183d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>()) { 184d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com const StackFrameContext *CalleeContext = CEE->getCalleeContext(); 185d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (CalleeContext->getCallSite() == S) { 186d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BR.markInteresting(CalleeContext); 187d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BR.addVisitor(new ReturnVisitor(CalleeContext)); 188d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 189d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 190d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 1910abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// Returns true if any counter-suppression heuristics are enabled for 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /// ReturnVisitor. 195a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com static bool hasCounterSuppression(AnalyzerOptions &Options) { 196a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com return Options.shouldAvoidSuppressingNullArgumentPaths(); 197a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1995bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com PathDiagnosticPiece *visitNodeInitial(const ExplodedNode *N, 2005bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com const ExplodedNode *PrevN, 2015bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com BugReporterContext &BRC, 2025bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com BugReport &BR) { 2035bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com // Only print a message at the interesting return statement. 2045bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (N->getLocationContext() != StackFrame) 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>(); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!SP) 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!Ret) 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2148136d58161c3fa314af42f5c65682be855dfec1breed@google.com 2158136d58161c3fa314af42f5c65682be855dfec1breed@google.com // Okay, we're at the right return statement, but do we have the return 2168136d58161c3fa314af42f5c65682be855dfec1breed@google.com // value available? 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramStateRef State = N->getState(); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SVal V = State->getSVal(Ret, StackFrame); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (V.isUnknownOrUndef()) 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Don't print any more notes after this one. 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Mode = Satisfied; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 225d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com const Expr *RetE = Ret->getRetValue(); 22682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com assert(RetE && "Tracking a return value for a void function"); 2277767cd87fdadeed868457a2407e8b0a50006fc4asenorblanco@chromium.org 228d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com // Handle cases where a reference is returned and then immediately used. 229d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com Optional<Loc> LValue; 230d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com if (RetE->isGLValue()) { 231d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com if ((LValue = V.getAs<Loc>())) { 232d4577757874d1dda1a3bffa3f2347c251859c27ereed@android.com SVal RValue = State->getRawSVal(*LValue, RetE->getType()); 233b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com if (RValue.getAs<DefinedSVal>()) 234b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com V = RValue; 235b757f8d20c582463999bd7aa5a48110e84945d19reed@android.com } 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2380abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // Ignore aggregate rvalues. 239a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (V.getAs<nonloc::LazyCompoundVal>() || 240a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com V.getAs<nonloc::CompoundVal>()) 241a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com return 0; 242a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 243a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com RetE = RetE->IgnoreParenCasts(); 244a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 245a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com // If we can't prove the return value is 0, just mark it interesting, and 246a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com // make sure to track it into any further inner functions. 247a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (State->assume(V.castAs<DefinedSVal>(), true)) { 248a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com BR.markInteresting(V); 249a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com ReturnVisitor::addVisitorIfNecessary(N, RetE, BR); 250a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com return 0; 251a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 25297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com 2530abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // If we're returning 0, we should track where that 0 came from. 254a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com bugreporter::trackNullOrUndefValue(N, RetE, BR); 2550abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 2560abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // Build an appropriate message based on the return value. 257900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SmallString<64> Msg; 258cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com llvm::raw_svector_ostream Out(Msg); 259fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2600abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (V.getAs<Loc>()) { 2610abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // If we are pruning null-return paths as unlikely error paths, mark the 2620abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // report invalid. We still want to emit a path note, however, in case 263a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // the report is resurrected as valid later on. 264cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com ExprEngine &Eng = BRC.getBugReporter().getEngine(); 2650abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com AnalyzerOptions &Options = Eng.getAnalysisManager().options; 2660abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (Options.shouldSuppressNullReturnPaths()) { 2670abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (hasCounterSuppression(Options)) 2680abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Mode = MaybeSuppress; 2690abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com else 2700abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com BR.markInvalid(ReturnVisitor::getTag(), StackFrame); 2710abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 2720abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 2730abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (RetE->getType()->isObjCObjectPointerType()) 27427e21fe577211c1c40cbf40d0385b02c69d04522skia.committer@gmail.com Out << "Returning nil"; 2750abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com else 2760abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Out << "Returning null pointer"; 2770abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } else { 2780abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Out << "Returning zero"; 2790abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 2800abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 2810abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (LValue) { 2820abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (const MemRegion *MR = LValue->getAsRegion()) { 2830abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (MR->canPrintPretty()) { 2840abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Out << " (reference to '"; 2850abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com MR->printPretty(Out); 2860abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Out << "')"; 2870abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 2880abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 2890abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } else { 2900abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // FIXME: We should have a more generalized location printing mechanism. 2910abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE)) 2920abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) 2930abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Out << " (loaded from '" << *DD << "')"; 294fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 295cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 296cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame); 2970abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com return new PathDiagnosticEventPiece(L, Out.str()); 2980abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } 2990abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 3000abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com PathDiagnosticPiece *visitNodeMaybeSuppress(const ExplodedNode *N, 3010abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com const ExplodedNode *PrevN, 3020abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com BugReporterContext &BRC, 3030abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com BugReport &BR) { 3040abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // Are we at the entry node for this call? 3050abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Optional<CallEnter> CE = N->getLocationAs<CallEnter>(); 3060abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (!CE) 3070abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com return 0; 3080abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 3090abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (CE->getCalleeContext() != StackFrame) 3100abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com return 0; 3110abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 3120abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com Mode = Satisfied; 3130abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 3140abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com ExprEngine &Eng = BRC.getBugReporter().getEngine(); 3150abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com AnalyzerOptions &Options = Eng.getAnalysisManager().options; 3160abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (Options.shouldAvoidSuppressingNullArgumentPaths()) { 3170abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // Don't automatically suppress a report if one of the arguments is 3180abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // known to be a null pointer. Instead, start tracking /that/ null 3190abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // value back to its origin. 3200abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com ProgramStateManager &StateMgr = BRC.getStateManager(); 3210abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com CallEventManager &CallMgr = StateMgr.getCallEventManager(); 3220abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 323cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com ProgramStateRef State = N->getState(); 324cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com CallEventRef<> Call = CallMgr.getCaller(StackFrame, State); 325cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) { 326cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com SVal ArgV = Call->getArgSVal(I); 327a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com if (!ArgV.getAs<Loc>()) 32897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com continue; 3290abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 330a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com const Expr *ArgE = Call->getArgExpr(I); 331900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (!ArgE) 332cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com continue; 333fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 334cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // Is it possible for this argument to be non-null? 335cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (State->assume(ArgV.castAs<Loc>(), true)) 336a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com continue; 337cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 338fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true)) 339cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com return 0; 340cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 3410abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // If we /can't/ track the null pointer, we should err on the side of 3420abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com // false negatives, and continue towards marking this report invalid. 343cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // (We will still look at the other arguments, though.) 344a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 345a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 346a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 34797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com // There is no reason not to suppress this report; go ahead and do it. 348a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com BR.markInvalid(ReturnVisitor::getTag(), StackFrame); 349a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com return 0; 350a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com } 351a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 352a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 353d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com const ExplodedNode *PrevN, 354d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BugReporterContext &BRC, 355d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BugReport &BR) { 356d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com switch (Mode) { 357d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com case Initial: 358d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return visitNodeInitial(N, PrevN, BRC, BR); 359d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com case MaybeSuppress: 360d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return visitNodeMaybeSuppress(N, PrevN, BRC, BR); 361d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com case Satisfied: 362d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return 0; 363d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 364d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 365d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com llvm_unreachable("Invalid visit mode!"); 366d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 367d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com}; 368d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com} // end anonymous namespace 369d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 370d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 371d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comvoid FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { 372d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com static int tag = 0; 373d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com ID.AddPointer(&tag); 374d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com ID.AddPointer(R); 375d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com ID.Add(V); 376d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com} 377f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org 378f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.orgPathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, 379f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org const ExplodedNode *Pred, 380d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BugReporterContext &BRC, 381d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BugReport &BR) { 382d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 383d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Satisfied) 384d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return NULL; 385d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 386d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com const ExplodedNode *StoreSite = 0; 387d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com const Expr *InitE = 0; 388d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com bool IsParam = false; 389d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 390c932c9fd77503aec47c256818dd94a8b57219a43robertphillips@google.com // First see if we reached the declaration of the region. 391d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 392d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Optional<PostStmt> P = Pred->getLocationAs<PostStmt>()) { 393d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) { 394d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (DS->getSingleDecl() == VR->getDecl()) { 395d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com StoreSite = Pred; 396d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com InitE = VR->getDecl()->getInit(); 397d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 398d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 399a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 400a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 401d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 402cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // Otherwise, see if this is the store site: 403cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // (1) Succ has this binding and Pred does not, i.e. this is 404cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // where the binding first occurred. 405cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // (2) Succ has this binding and is a PostStore node for this region, i.e. 406cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // the same binding was re-assigned here. 407cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (!StoreSite) { 408cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (Succ->getState()->getSVal(R) != V) 409cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com return NULL; 410cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 411cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (Pred->getState()->getSVal(R) == V) { 412cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com Optional<PostStore> PS = Succ->getLocationAs<PostStore>(); 413d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (!PS || PS->getLocationValue() != R) 414d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com return NULL; 415d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 416d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 417d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com StoreSite = Succ; 418d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 419d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // If this is an assignment expression, we can track the value 420d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // being assigned. 421d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>()) 422d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) 423d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (BO->isAssignmentOp()) 424d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com InitE = BO->getRHS(); 425d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com 426d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // If this is a call entry, the variable should be a parameter. 427d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // FIXME: Handle CXXThisRegion as well. (This is not a priority because 428d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // 'this' should never be NULL, but this visitor isn't just for NULL and 429d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com // UndefinedVal.) 430d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) { 431cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 432cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 433045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 434045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ProgramStateManager &StateMgr = BRC.getStateManager(); 435cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com CallEventManager &CallMgr = StateMgr.getCallEventManager(); 436a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org 437cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), 438cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com Succ->getState()); 439cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); 440848250415eddc54075f7eb8795e8db79e749c6abreed IsParam = true; 4419be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com } 4429be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com } 4439be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com } 4449be5727d96979f6a0f89b00a43c19bca97ace0fcreed@google.com 445cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (!StoreSite) 446a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org return NULL; 447cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com Satisfied = true; 448cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 449fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // If we have an expression that provided the value, try to track where it 450cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com // came from. 451045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (InitE) { 452045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (V.isUndef() || V.getAs<loc::ConcreteInt>()) { 453cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (!IsParam) 454cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com InitE = InitE->IgnoreParenCasts(); 455cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam); 456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } else { 4570c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), 458d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com BR); 459d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 460d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com } 4610c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com 4620c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com if (!R->canPrintPretty()) 4630c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com return 0; 4640c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com 4650c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com // Okay, we've found the binding. Emit an appropriate message. 4660c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com SmallString<256> sbuf; 4670c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com llvm::raw_svector_ostream os(sbuf); 4680abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com 4690c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) { 4700abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com const Stmt *S = PS->getStmt(); 4710c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com const char *action = 0; 4720c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com const DeclStmt *DS = dyn_cast<DeclStmt>(S); 4730c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com const VarRegion *VR = dyn_cast<VarRegion>(R); 4740c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com 4750abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com if (DS) { 4760c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com action = "initialized to "; 4770abbff9987b9452fd30cce198bea34fdb210ac41bungeman@google.com } else if (isa<BlockExpr>(S)) { 4780c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com action = "captured by block as "; 4790c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com if (VR) { 4800c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com // See if we can get the BlockVarRegion. 4810c5f3762e863411798b1d6c55157d24c69d5bc25bungeman@google.com ProgramStateRef State = StoreSite->getState(); 482cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com SVal V = State->getSVal(S, PS->getLocationContext()); 483cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (const BlockDataRegion *BDR = 484cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { 4855bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { 4865bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (Optional<KnownSVal> KV = 4875bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com State->getSVal(OriginalR).getAs<KnownSVal>()) 4885bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com BR.addVisitor(new FindLastStoreBRVisitor(*KV, OriginalR)); 4895bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 4905bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 4915bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 4925bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 4935bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 4945bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (action) { 4955bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (!R) 4965bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com return 0; 4975bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 4985bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << '\''; 4995bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com R->printPretty(os); 5005bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << "' "; 5015bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 5025bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (V.getAs<loc::ConcreteInt>()) { 5035bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com bool b = false; 5045bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (R->isBoundable()) { 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (TR->getValueType()->isObjCObjectPointerType()) { 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << action << "nil"; 508fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com b = true; 5095bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5105bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5115bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5125bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 5135bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (!b) 5145bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << action << "a null pointer value"; 5155bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } else if (Optional<nonloc::ConcreteInt> CVal = 5165bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com V.getAs<nonloc::ConcreteInt>()) { 5175bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << action << CVal->getValue(); 5185bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (DS) { 520ce2b1afb582f0a2274f476c949cff8b0e1c72b36reed@google.com if (V.isUndef()) { 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (isa<VarRegion>(R)) { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (VD->getInit()) 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "initialized to a garbage value"; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "declared without an initial value"; 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "initialized here"; 5315bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5325bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5335bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5345bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } else if (StoreSite->getLocation().getAs<CallEnter>()) { 5355bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 5365bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 5375bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "Passing "; 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (V.getAs<loc::ConcreteInt>()) { 541a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com if (Param->getType()->isObjCObjectPointerType()) 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "nil object reference"; 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 544cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com os << "null pointer value"; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (V.isUndef()) { 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "uninitialized value"; 547cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com } else if (Optional<nonloc::ConcreteInt> CI = 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com V.getAs<nonloc::ConcreteInt>()) { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "the value " << CI->getValue(); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5514516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com os << "value"; 55282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Printed parameter indexes are 1-based, not 0-based. 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned Idx = Param->getFunctionScopeIndex() + 1; 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter '"; 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 558a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com R->printPretty(os); 559a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com os << '\''; 56097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5625bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 563a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (os.str().empty()) { 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (V.getAs<loc::ConcreteInt>()) { 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool b = false; 5661b27704eba15be4e9d1997faac42038493a30be5djsollen if (R->isBoundable()) { 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (TR->getValueType()->isObjCObjectPointerType()) { 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com os << "nil object reference stored to "; 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b = true; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5755bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com if (!b) 5765bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << "Null pointer value stored to "; 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5785bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com else if (V.isUndef()) { 5795bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << "Uninitialized value stored to "; 5805bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } else if (Optional<nonloc::ConcreteInt> CV = 5815bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com V.getAs<nonloc::ConcreteInt>()) { 5825bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << "The value " << CV->getValue() << " is assigned to "; 5835bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com } 5845bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com else 5855bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << "Value assigned to "; 5865bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 5875bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com os << '\''; 5885bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com R->printPretty(os); 5892fd42c471c77f54ace35c13975651e17d5b2e8c6skia.committer@gmail.com os << '\''; 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Construct a new PathDiagnosticPiece. 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramPoint P = StoreSite->getLocation(); 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PathDiagnosticLocation L; 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (P.getAs<CallEnter>() && InitE) 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com L = PathDiagnosticLocation(InitE, BRC.getSourceManager(), 59782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com P.getLocationContext()); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!L.isValid()) 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return new PathDiagnosticEventPiece(L, os.str()); 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static int tag = 0; 6074516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com ID.AddPointer(&tag); 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ID.AddBoolean(Assumption); 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ID.Add(Constraint); 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// Return the tag associated with this visitor. This tag will be used 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/// to make all PathDiagnosticPieces created by this visitor. 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char *TrackConstraintBRVisitor::getTag() { 61597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return "TrackConstraintBRVisitor"; 616a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com} 617a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 618a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comPathDiagnosticPiece * 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ExplodedNode *PrevN, 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReporterContext &BRC, 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BugReport &BR) { 6237db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (isSatisfied) 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Check if in the previous state it was feasible for this constraint 6270a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com // to *not* be true. 628410780677af260e32948b02c0725ef6ad761260cbungeman if (PrevN->getState()->assume(Constraint, !Assumption)) { 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com isSatisfied = true; 6319d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com 6329d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com // As a sanity check, make sure that the negation of the constraint 6339d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com // was infeasible in the current state. If it is feasible, we somehow 6349d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com // missed the transition point. 6357db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (N->getState()->assume(Constraint, !Assumption)) 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 6377db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 6387db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // We found the transition point for the constraint. We now need to 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pretty-print the constraint. (work-in-progress) 6401b27704eba15be4e9d1997faac42038493a30be5djsollen std::string sbuf; 64182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com llvm::raw_string_ostream os(sbuf); 642cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 643cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (Constraint.getAs<Loc>()) { 644cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com os << "Assuming pointer value is "; 645cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com os << (Assumption ? "non-null" : "null"); 646cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com } 647cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com 648cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com if (os.str().empty()) 649cf598b176da861a8fd1a4e2386a7ddf874684bb3reed@google.com return NULL; 6507db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Construct a new PathDiagnosticPiece. 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramPoint P = N->getLocation(); 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PathDiagnosticLocation L = 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PathDiagnosticLocation::create(P, BRC.getSourceManager()); 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!L.isValid()) 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str()); 6599575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com X->setTag(getTag()); 6609575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com return X; 6619575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com } 6629575fb8b1d505572dd9808af1697921fe48c021ebungeman@google.com 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 666fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.combool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, 667fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com BugReport &report, bool IsArg) { 668fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com if (!S || !N) 669fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com return false; 670fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com 671fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) 672fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com S = OVE->getSourceExpr(); 673fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com 674fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com if (IsArg) { 675fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call"); 676fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com } else { 677fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // Walk through nodes until we get one that matches the statement exactly. 6787db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com do { 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ProgramPoint &pp = N->getLocation(); 6804bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (Optional<PostStmt> ps = pp.getAs<PostStmt>()) { 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ps->getStmt() == S) 6827db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com break; 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) { 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (CEE->getCalleeContext()->getCallSite() == S) 685fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com break; 686fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com } 687fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com N = N->getFirstPred(); 688fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com } while (N); 689fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!N) 69182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com return false; 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6937db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramStateRef state = N->getState(); 6957db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 6967db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // See if the expression we're interested refers to a variable. 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // If so, we can track both its contents and constraints on its value. 6987db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (const Expr *Ex = dyn_cast<Expr>(S)) { 6997db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // Strip off parens and casts. Note that this will never have issues with 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // C++ user-defined implicit conversions, because those have a constructor 7017db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // or function call inside. 7027db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com Ex = Ex->IgnoreParenCasts(); 7037db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ExplodedGraph::isInterestingLValueExpr(Ex)) { 7057db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com const MemRegion *R = 0; 7067db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 7077db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // First check if this is a DeclRefExpr for a C++ reference type. 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // For those, we want the location of the reference. 7097db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 7117db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (VD->getType()->isReferenceType()) { 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramStateManager &StateMgr = state->getStateManager(); 71382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com MemRegionManager &MRMgr = StateMgr.getRegionManager(); 7147db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com R = MRMgr.getVarRegion(VD, N->getLocationContext()); 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7167db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com } 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 71882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 7197db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // For all other cases, find the location by scouring the ExplodedGraph. 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!R) { 7217db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // Find the ExplodedNode where the lvalue (the value of 'Ex') 7227db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // was computed. We need this for getting the location value. 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ExplodedNode *LVNode = N; 7247db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com const Expr *SearchEx = Ex; 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (const OpaqueValueExpr *OPE = dyn_cast<OpaqueValueExpr>(Ex)) { 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SearchEx = OPE->getSourceExpr(); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 728a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com while (LVNode) { 72950dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) { 73050dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com if (P->getStmt() == SearchEx) 73150dd41017ad121b5f40f063d813ba517668fcfbcbungeman@google.com break; 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com LVNode = LVNode->getFirstPred(); 734a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com } 735ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com assert(LVNode && "Unable to find the lvalue node."); 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ProgramStateRef LVState = LVNode->getState(); 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (Optional<Loc> L = 738a9d4e84c435f61be3c02d7f54acab973e8b7761creed@google.com LVState->getSVal(Ex, LVNode->getLocationContext()).getAs<Loc>()) { 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com R = L->getAsRegion(); 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7427db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com 7437db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com if (R) { 7447db9fe65b2bb099e9dc41f79cc15b6a7a142bed6reed@google.com // Mark both the variable region and its contents as interesting. 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SVal V = state->getRawSVal(loc::MemRegionVal(R)); 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7472e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com // If the value matches the default for the variable region, that 7482e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com // might mean that it's been cleared out of the state. Fall back to 749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // the full argument expression (with casts and such intact). 7502e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com if (IsArg) { 7512e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant(); 7522e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com if (!UseArgValue) { 7532e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com const SymbolRegionValue *SRV = 7542e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com dyn_cast_or_null<SymbolRegionValue>(V.getAsLocSymbol()); 7552e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com if (SRV) 7562e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com UseArgValue = (SRV->getRegion() == R); 7572e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com } 7582e68478d8654c8a4048b45ad16ac039dadb25c33reed@google.com if (UseArgValue) 75962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 76062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com report.markInteresting(R); 76362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com report.markInteresting(V); 76462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com report.addVisitor(new UndefOrNullArgVisitor(R)); 7650da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com 7660da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com if (isa<SymbolicRegion>(R)) { 76762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com TrackConstraintBRVisitor *VI = 76862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com new TrackConstraintBRVisitor(loc::MemRegionVal(R), false); 769a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com report.addVisitor(VI); 77062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 77162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 772a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com // If the contents are symbolic, find out when they became null. 77362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (V.getAsLocSymbol()) { 77462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com BugReporterVisitor *ConstraintTracker = 775a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false); 77662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com report.addVisitor(ConstraintTracker); 77762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 778a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com 77962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (Optional<KnownSVal> KV = V.getAs<KnownSVal>()) 78062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com report.addVisitor(new FindLastStoreBRVisitor(*KV, R)); 781a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com return true; 782a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com } 783410780677af260e32948b02c0725ef6ad761260cbungeman } 784410780677af260e32948b02c0725ef6ad761260cbungeman } 785410780677af260e32948b02c0725ef6ad761260cbungeman 78662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com // If the expression is not an "lvalue expression", we can still 78762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com // track the constraints on its contents. 78862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 78962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 790f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // If the value came from an inlined function call, we should at least make 791f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com // sure that function isn't pruned in our output. 79284e22d847fc84727bc220947162363ee1fe068fcreed@google.com if (const Expr *E = dyn_cast<Expr>(S)) 79384e22d847fc84727bc220947162363ee1fe068fcreed@google.com S = E->IgnoreParenCasts(); 79484e22d847fc84727bc220947162363ee1fe068fcreed@google.com ReturnVisitor::addVisitorIfNecessary(N, S, report); 79584e22d847fc84727bc220947162363ee1fe068fcreed@google.com 79684e22d847fc84727bc220947162363ee1fe068fcreed@google.com // Uncomment this to find cases where we aren't properly getting the 7970da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com // base value that was dereferenced. 7980da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com // assert(!V.isUnknownOrUndef()); 79962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com // Is it a symbolic value? 80062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) { 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // At this point we are dealing with the region's LValue. 802 // However, if the rvalue is a symbolic region, we should track it as well. 803 SVal RVal = state->getSVal(L->getRegion()); 804 const MemRegion *RegionRVal = RVal.getAsRegion(); 805 report.addVisitor(new UndefOrNullArgVisitor(L->getRegion())); 806 807 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { 808 report.markInteresting(RegionRVal); 809 report.addVisitor(new TrackConstraintBRVisitor( 810 loc::MemRegionVal(RegionRVal), false)); 811 } 812 } 813 814 return true; 815} 816 817BugReporterVisitor * 818FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N, 819 const MemRegion *R) { 820 assert(R && "The memory region is null."); 821 822 ProgramStateRef state = N->getState(); 823 if (Optional<KnownSVal> KV = state->getSVal(R).getAs<KnownSVal>()) 824 return new FindLastStoreBRVisitor(*KV, R); 825 return 0; 826} 827 828PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 829 const ExplodedNode *PrevN, 830 BugReporterContext &BRC, 831 BugReport &BR) { 832 Optional<PostStmt> P = N->getLocationAs<PostStmt>(); 833 if (!P) 834 return 0; 835 const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); 836 if (!ME) 837 return 0; 838 const Expr *Receiver = ME->getInstanceReceiver(); 839 if (!Receiver) 840 return 0; 841 ProgramStateRef state = N->getState(); 842 const SVal &V = state->getSVal(Receiver, N->getLocationContext()); 843 Optional<DefinedOrUnknownSVal> DV = V.getAs<DefinedOrUnknownSVal>(); 844 if (!DV) 845 return 0; 846 state = state->assume(*DV, true); 847 if (state) 848 return 0; 849 850 // The receiver was nil, and hence the method was skipped. 851 // Register a BugReporterVisitor to issue a message telling us how 852 // the receiver was null. 853 bugreporter::trackNullOrUndefValue(N, Receiver, BR); 854 // Issue a message saying that the method was skipped. 855 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 856 N->getLocationContext()); 857 return new PathDiagnosticEventPiece(L, "No method is called " 858 "because the receiver is nil"); 859} 860 861// Registers every VarDecl inside a Stmt with a last store visitor. 862void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 863 const Stmt *S) { 864 const ExplodedNode *N = BR.getErrorNode(); 865 std::deque<const Stmt *> WorkList; 866 WorkList.push_back(S); 867 868 while (!WorkList.empty()) { 869 const Stmt *Head = WorkList.front(); 870 WorkList.pop_front(); 871 872 ProgramStateRef state = N->getState(); 873 ProgramStateManager &StateMgr = state->getStateManager(); 874 875 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 876 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 877 const VarRegion *R = 878 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 879 880 // What did we load? 881 SVal V = state->getSVal(S, N->getLocationContext()); 882 883 if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) { 884 // Register a new visitor with the BugReport. 885 BR.addVisitor(new FindLastStoreBRVisitor(V.castAs<KnownSVal>(), R)); 886 } 887 } 888 } 889 890 for (Stmt::const_child_iterator I = Head->child_begin(); 891 I != Head->child_end(); ++I) 892 WorkList.push_back(*I); 893 } 894} 895 896//===----------------------------------------------------------------------===// 897// Visitor that tries to report interesting diagnostics from conditions. 898//===----------------------------------------------------------------------===// 899 900/// Return the tag associated with this visitor. This tag will be used 901/// to make all PathDiagnosticPieces created by this visitor. 902const char *ConditionBRVisitor::getTag() { 903 return "ConditionBRVisitor"; 904} 905 906PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 907 const ExplodedNode *Prev, 908 BugReporterContext &BRC, 909 BugReport &BR) { 910 PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR); 911 if (piece) { 912 piece->setTag(getTag()); 913 if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece)) 914 ev->setPrunable(true, /* override */ false); 915 } 916 return piece; 917} 918 919PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 920 const ExplodedNode *Prev, 921 BugReporterContext &BRC, 922 BugReport &BR) { 923 924 ProgramPoint progPoint = N->getLocation(); 925 ProgramStateRef CurrentState = N->getState(); 926 ProgramStateRef PrevState = Prev->getState(); 927 928 // Compare the GDMs of the state, because that is where constraints 929 // are managed. Note that ensure that we only look at nodes that 930 // were generated by the analyzer engine proper, not checkers. 931 if (CurrentState->getGDM().getRoot() == 932 PrevState->getGDM().getRoot()) 933 return 0; 934 935 // If an assumption was made on a branch, it should be caught 936 // here by looking at the state transition. 937 if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) { 938 const CFGBlock *srcBlk = BE->getSrc(); 939 if (const Stmt *term = srcBlk->getTerminator()) 940 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); 941 return 0; 942 } 943 944 if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) { 945 // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 946 // violation. 947 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 948 cast<GRBugReporter>(BRC.getBugReporter()). 949 getEngine().geteagerlyAssumeBinOpBifurcationTags(); 950 951 const ProgramPointTag *tag = PS->getTag(); 952 if (tag == tags.first) 953 return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 954 BRC, BR, N); 955 if (tag == tags.second) 956 return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 957 BRC, BR, N); 958 959 return 0; 960 } 961 962 return 0; 963} 964 965PathDiagnosticPiece * 966ConditionBRVisitor::VisitTerminator(const Stmt *Term, 967 const ExplodedNode *N, 968 const CFGBlock *srcBlk, 969 const CFGBlock *dstBlk, 970 BugReport &R, 971 BugReporterContext &BRC) { 972 const Expr *Cond = 0; 973 974 switch (Term->getStmtClass()) { 975 default: 976 return 0; 977 case Stmt::IfStmtClass: 978 Cond = cast<IfStmt>(Term)->getCond(); 979 break; 980 case Stmt::ConditionalOperatorClass: 981 Cond = cast<ConditionalOperator>(Term)->getCond(); 982 break; 983 } 984 985 assert(Cond); 986 assert(srcBlk->succ_size() == 2); 987 const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 988 return VisitTrueTest(Cond, tookTrue, BRC, R, N); 989} 990 991PathDiagnosticPiece * 992ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 993 bool tookTrue, 994 BugReporterContext &BRC, 995 BugReport &R, 996 const ExplodedNode *N) { 997 998 const Expr *Ex = Cond; 999 1000 while (true) { 1001 Ex = Ex->IgnoreParenCasts(); 1002 switch (Ex->getStmtClass()) { 1003 default: 1004 return 0; 1005 case Stmt::BinaryOperatorClass: 1006 return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, 1007 R, N); 1008 case Stmt::DeclRefExprClass: 1009 return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, 1010 R, N); 1011 case Stmt::UnaryOperatorClass: { 1012 const UnaryOperator *UO = cast<UnaryOperator>(Ex); 1013 if (UO->getOpcode() == UO_LNot) { 1014 tookTrue = !tookTrue; 1015 Ex = UO->getSubExpr(); 1016 continue; 1017 } 1018 return 0; 1019 } 1020 } 1021 } 1022} 1023 1024bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out, 1025 BugReporterContext &BRC, 1026 BugReport &report, 1027 const ExplodedNode *N, 1028 Optional<bool> &prunable) { 1029 const Expr *OriginalExpr = Ex; 1030 Ex = Ex->IgnoreParenCasts(); 1031 1032 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 1033 const bool quotes = isa<VarDecl>(DR->getDecl()); 1034 if (quotes) { 1035 Out << '\''; 1036 const LocationContext *LCtx = N->getLocationContext(); 1037 const ProgramState *state = N->getState().getPtr(); 1038 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 1039 LCtx).getAsRegion()) { 1040 if (report.isInteresting(R)) 1041 prunable = false; 1042 else { 1043 const ProgramState *state = N->getState().getPtr(); 1044 SVal V = state->getSVal(R); 1045 if (report.isInteresting(V)) 1046 prunable = false; 1047 } 1048 } 1049 } 1050 Out << DR->getDecl()->getDeclName().getAsString(); 1051 if (quotes) 1052 Out << '\''; 1053 return quotes; 1054 } 1055 1056 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 1057 QualType OriginalTy = OriginalExpr->getType(); 1058 if (OriginalTy->isPointerType()) { 1059 if (IL->getValue() == 0) { 1060 Out << "null"; 1061 return false; 1062 } 1063 } 1064 else if (OriginalTy->isObjCObjectPointerType()) { 1065 if (IL->getValue() == 0) { 1066 Out << "nil"; 1067 return false; 1068 } 1069 } 1070 1071 Out << IL->getValue(); 1072 return false; 1073 } 1074 1075 return false; 1076} 1077 1078PathDiagnosticPiece * 1079ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 1080 const BinaryOperator *BExpr, 1081 const bool tookTrue, 1082 BugReporterContext &BRC, 1083 BugReport &R, 1084 const ExplodedNode *N) { 1085 1086 bool shouldInvert = false; 1087 Optional<bool> shouldPrune; 1088 1089 SmallString<128> LhsString, RhsString; 1090 { 1091 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 1092 const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, 1093 shouldPrune); 1094 const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, 1095 shouldPrune); 1096 1097 shouldInvert = !isVarLHS && isVarRHS; 1098 } 1099 1100 BinaryOperator::Opcode Op = BExpr->getOpcode(); 1101 1102 if (BinaryOperator::isAssignmentOp(Op)) { 1103 // For assignment operators, all that we care about is that the LHS 1104 // evaluates to "true" or "false". 1105 return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 1106 BRC, R, N); 1107 } 1108 1109 // For non-assignment operations, we require that we can understand 1110 // both the LHS and RHS. 1111 if (LhsString.empty() || RhsString.empty()) 1112 return 0; 1113 1114 // Should we invert the strings if the LHS is not a variable name? 1115 SmallString<256> buf; 1116 llvm::raw_svector_ostream Out(buf); 1117 Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 1118 1119 // Do we need to invert the opcode? 1120 if (shouldInvert) 1121 switch (Op) { 1122 default: break; 1123 case BO_LT: Op = BO_GT; break; 1124 case BO_GT: Op = BO_LT; break; 1125 case BO_LE: Op = BO_GE; break; 1126 case BO_GE: Op = BO_LE; break; 1127 } 1128 1129 if (!tookTrue) 1130 switch (Op) { 1131 case BO_EQ: Op = BO_NE; break; 1132 case BO_NE: Op = BO_EQ; break; 1133 case BO_LT: Op = BO_GE; break; 1134 case BO_GT: Op = BO_LE; break; 1135 case BO_LE: Op = BO_GT; break; 1136 case BO_GE: Op = BO_LT; break; 1137 default: 1138 return 0; 1139 } 1140 1141 switch (Op) { 1142 case BO_EQ: 1143 Out << "equal to "; 1144 break; 1145 case BO_NE: 1146 Out << "not equal to "; 1147 break; 1148 default: 1149 Out << BinaryOperator::getOpcodeStr(Op) << ' '; 1150 break; 1151 } 1152 1153 Out << (shouldInvert ? LhsString : RhsString); 1154 const LocationContext *LCtx = N->getLocationContext(); 1155 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 1156 PathDiagnosticEventPiece *event = 1157 new PathDiagnosticEventPiece(Loc, Out.str()); 1158 if (shouldPrune.hasValue()) 1159 event->setPrunable(shouldPrune.getValue()); 1160 return event; 1161} 1162 1163PathDiagnosticPiece * 1164ConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 1165 const Expr *CondVarExpr, 1166 const bool tookTrue, 1167 BugReporterContext &BRC, 1168 BugReport &report, 1169 const ExplodedNode *N) { 1170 // FIXME: If there's already a constraint tracker for this variable, 1171 // we shouldn't emit anything here (c.f. the double note in 1172 // test/Analysis/inlining/path-notes.c) 1173 SmallString<256> buf; 1174 llvm::raw_svector_ostream Out(buf); 1175 Out << "Assuming " << LhsString << " is "; 1176 1177 QualType Ty = CondVarExpr->getType(); 1178 1179 if (Ty->isPointerType()) 1180 Out << (tookTrue ? "not null" : "null"); 1181 else if (Ty->isObjCObjectPointerType()) 1182 Out << (tookTrue ? "not nil" : "nil"); 1183 else if (Ty->isBooleanType()) 1184 Out << (tookTrue ? "true" : "false"); 1185 else if (Ty->isIntegerType()) 1186 Out << (tookTrue ? "non-zero" : "zero"); 1187 else 1188 return 0; 1189 1190 const LocationContext *LCtx = N->getLocationContext(); 1191 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 1192 PathDiagnosticEventPiece *event = 1193 new PathDiagnosticEventPiece(Loc, Out.str()); 1194 1195 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { 1196 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 1197 const ProgramState *state = N->getState().getPtr(); 1198 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1199 if (report.isInteresting(R)) 1200 event->setPrunable(false); 1201 } 1202 } 1203 } 1204 1205 return event; 1206} 1207 1208PathDiagnosticPiece * 1209ConditionBRVisitor::VisitTrueTest(const Expr *Cond, 1210 const DeclRefExpr *DR, 1211 const bool tookTrue, 1212 BugReporterContext &BRC, 1213 BugReport &report, 1214 const ExplodedNode *N) { 1215 1216 const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 1217 if (!VD) 1218 return 0; 1219 1220 SmallString<256> Buf; 1221 llvm::raw_svector_ostream Out(Buf); 1222 1223 Out << "Assuming '"; 1224 VD->getDeclName().printName(Out); 1225 Out << "' is "; 1226 1227 QualType VDTy = VD->getType(); 1228 1229 if (VDTy->isPointerType()) 1230 Out << (tookTrue ? "non-null" : "null"); 1231 else if (VDTy->isObjCObjectPointerType()) 1232 Out << (tookTrue ? "non-nil" : "nil"); 1233 else if (VDTy->isScalarType()) 1234 Out << (tookTrue ? "not equal to 0" : "0"); 1235 else 1236 return 0; 1237 1238 const LocationContext *LCtx = N->getLocationContext(); 1239 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 1240 PathDiagnosticEventPiece *event = 1241 new PathDiagnosticEventPiece(Loc, Out.str()); 1242 1243 const ProgramState *state = N->getState().getPtr(); 1244 if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 1245 if (report.isInteresting(R)) 1246 event->setPrunable(false); 1247 else { 1248 SVal V = state->getSVal(R); 1249 if (report.isInteresting(V)) 1250 event->setPrunable(false); 1251 } 1252 } 1253 return event; 1254} 1255 1256PathDiagnosticPiece * 1257LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, 1258 const ExplodedNode *N, 1259 BugReport &BR) { 1260 const Stmt *S = BR.getStmt(); 1261 if (!S) 1262 return 0; 1263 1264 // Here we suppress false positives coming from system macros. This list is 1265 // based on known issues. 1266 1267 // Skip reports within the sys/queue.h macros as we do not have the ability to 1268 // reason about data structure shapes. 1269 SourceManager &SM = BRC.getSourceManager(); 1270 SourceLocation Loc = S->getLocStart(); 1271 while (Loc.isMacroID()) { 1272 if (SM.isInSystemMacro(Loc) && 1273 (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) { 1274 BR.markInvalid(getTag(), 0); 1275 return 0; 1276 } 1277 Loc = SM.getSpellingLoc(Loc); 1278 } 1279 1280 return 0; 1281} 1282 1283PathDiagnosticPiece * 1284UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, 1285 const ExplodedNode *PrevN, 1286 BugReporterContext &BRC, 1287 BugReport &BR) { 1288 1289 ProgramStateRef State = N->getState(); 1290 ProgramPoint ProgLoc = N->getLocation(); 1291 1292 // We are only interested in visiting CallEnter nodes. 1293 Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>(); 1294 if (!CEnter) 1295 return 0; 1296 1297 // Check if one of the arguments is the region the visitor is tracking. 1298 CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); 1299 CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); 1300 unsigned Idx = 0; 1301 for (CallEvent::param_iterator I = Call->param_begin(), 1302 E = Call->param_end(); I != E; ++I, ++Idx) { 1303 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); 1304 1305 // Are we tracking the argument or its subregion? 1306 if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) 1307 continue; 1308 1309 // Check the function parameter type. 1310 const ParmVarDecl *ParamDecl = *I; 1311 assert(ParamDecl && "Formal parameter has no decl?"); 1312 QualType T = ParamDecl->getType(); 1313 1314 if (!(T->isAnyPointerType() || T->isReferenceType())) { 1315 // Function can only change the value passed in by address. 1316 continue; 1317 } 1318 1319 // If it is a const pointer value, the function does not intend to 1320 // change the value. 1321 if (T->getPointeeType().isConstQualified()) 1322 continue; 1323 1324 // Mark the call site (LocationContext) as interesting if the value of the 1325 // argument is undefined or '0'/'NULL'. 1326 SVal BoundVal = State->getSVal(R); 1327 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { 1328 BR.markInteresting(CEnter->getCalleeContext()); 1329 return 0; 1330 } 1331 } 1332 return 0; 1333} 1334