15350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// 25350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// 35350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// The LLVM Compiler Infrastructure 45350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// 55350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// This file is distributed under the University of Illinois Open Source 65350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// License. See LICENSE.TXT for details. 75350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// 85350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 95350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// 105350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// This file defines a set of BugReporter "visitors" which can be used to 115350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// enhance the diagnostics reported for a bug. 125350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// 135350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 1450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 155350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek#include "clang/AST/Expr.h" 165350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek#include "clang/AST/ExprObjC.h" 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 1980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 21681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 238fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 2485e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose#include "llvm/ADT/StringExtras.h" 25a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h" 265350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 275350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenekusing namespace clang; 289ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 295350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 30cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaksusing llvm::FoldingSetNodeID; 31cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 325350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 335350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// Utility functions. 345350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 355350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 369b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaksbool bugreporter::isDeclRefExprToReference(const Expr *E) { 379b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 389b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks return DRE->getDecl()->getType()->isReferenceType(); 399b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks } 409b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks return false; 419b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks} 429b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks 43dede2fd56d053a114a65ba72583981ce7aab27daJordan Roseconst Expr *bugreporter::getDerefExpr(const Stmt *S) { 4486f1745be24c834175e7a8a51b12f9a0063d532eAnna Zaks // Pattern match for a few useful cases: 455350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek // a[0], p->f, *p 46dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose const Expr *E = dyn_cast<Expr>(S); 47dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose if (!E) 486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 49dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose E = E->IgnoreParenCasts(); 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5111abcecc8c919673237cf37384290a1ef1943976Ted Kremenek while (true) { 52dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) { 5311abcecc8c919673237cf37384290a1ef1943976Ted Kremenek assert(B->isAssignmentOp()); 54dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose E = B->getLHS()->IgnoreParenCasts(); 5511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek continue; 5611abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 57dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) { 5811abcecc8c919673237cf37384290a1ef1943976Ted Kremenek if (U->getOpcode() == UO_Deref) 5911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return U->getSubExpr()->IgnoreParenCasts(); 6011abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 61dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { 629b925ac059089dfe74e3b8fa5effe519fb9ee885Anna Zaks if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) { 63d91696e8680bbe89df1076fded1bc54104526060Anna Zaks return ME->getBase()->IgnoreParenCasts(); 641e1d011874340f33b807ac90609424f90f72488aAnna Zaks } else { 651e1d011874340f33b807ac90609424f90f72488aAnna Zaks // If we have a member expr with a dot, the base must have been 661e1d011874340f33b807ac90609424f90f72488aAnna Zaks // dereferenced. 671e1d011874340f33b807ac90609424f90f72488aAnna Zaks return getDerefExpr(ME->getBase()); 68d91696e8680bbe89df1076fded1bc54104526060Anna Zaks } 6911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 70dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) { 71991bcb4370fe849603346ebbddc8dd47bc29d235Jordan Rose return IvarRef->getBase()->IgnoreParenCasts(); 72991bcb4370fe849603346ebbddc8dd47bc29d235Jordan Rose } 73dede2fd56d053a114a65ba72583981ce7aab27daJordan Rose else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) { 7411abcecc8c919673237cf37384290a1ef1943976Ted Kremenek return AE->getBase(); 7511abcecc8c919673237cf37384290a1ef1943976Ted Kremenek } 7686f1745be24c834175e7a8a51b12f9a0063d532eAnna Zaks else if (isDeclRefExprToReference(E)) { 7786f1745be24c834175e7a8a51b12f9a0063d532eAnna Zaks return E; 7886f1745be24c834175e7a8a51b12f9a0063d532eAnna Zaks } 7911abcecc8c919673237cf37384290a1ef1943976Ted Kremenek break; 805350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 835350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek} 845350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 855a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidisconst Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { 866403b57eda05a22273d920ad0bd2991d11eaa7b8Zhongxing Xu const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); 875350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) 885350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek return BE->getRHS(); 896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 905350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek} 915350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 925a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidisconst Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { 935350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); 945350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) 955350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek return RS->getRetValue(); 966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 975350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek} 985350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 995350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 1005350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek// Definitions for bug reporter visitors. 1015350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek//===----------------------------------------------------------------------===// 10223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 10323f395ee1bf4e4aa76b310d896a951799eaca94aAnna ZaksPathDiagnosticPiece* 10423f395ee1bf4e4aa76b310d896a951799eaca94aAnna ZaksBugReporterVisitor::getEndPath(BugReporterContext &BRC, 10523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks const ExplodedNode *EndPathNode, 10623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks BugReport &BR) { 1076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 10823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks} 10923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 11023f395ee1bf4e4aa76b310d896a951799eaca94aAnna ZaksPathDiagnosticPiece* 11123f395ee1bf4e4aa76b310d896a951799eaca94aAnna ZaksBugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, 11223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks const ExplodedNode *EndPathNode, 11323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks BugReport &BR) { 1145a0917d1367115d5fddfe7551f8634759217b54bAnna Zaks PathDiagnosticLocation L = 1155a0917d1367115d5fddfe7551f8634759217b54bAnna Zaks PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); 11623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 11723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks BugReport::ranges_iterator Beg, End; 118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(Beg, End) = BR.getRanges(); 11923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 12023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // Only add the statement itself as a range if we didn't specify any 12123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks // special ranges for this report. 12223f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, 12323f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks BR.getDescription(), 12423f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks Beg == End); 12523f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks for (; Beg != End; ++Beg) 12623f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks P->addRange(*Beg); 12723f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 12823f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks return P; 12923f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks} 13023f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 13123f395ee1bf4e4aa76b310d896a951799eaca94aAnna Zaks 1327aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rosenamespace { 1337aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// Emits an extra note at the return statement of an interesting stack frame. 1347aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// 1357aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// The returned value is marked as an interesting value, and if it's null, 1367aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// adds a visitor to track where it became null. 1377aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// 1387aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// This visitor is intended to be used when another visitor discovers that an 1397aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose/// interesting value comes from an inlined function call. 1407aba1171b32265b2206f3fa8f8886953051b58f5Jordan Roseclass ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> { 1417aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose const StackFrameContext *StackFrame; 1426a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose enum { 1436a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose Initial, 1448c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose MaybeUnsuppress, 1456a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose Satisfied 1466a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } Mode; 147aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks 148aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bool EnableNullFPSuppression; 1496a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 1507aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rosepublic: 1518c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose ReturnVisitor(const StackFrameContext *Frame, bool Suppressed) 152aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {} 1537aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 154b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose static void *getTag() { 1557aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose static int Tag = 0; 156b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose return static_cast<void *>(&Tag); 157b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose } 158b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Profile(llvm::FoldingSetNodeID &ID) const override { 160b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose ID.AddPointer(ReturnVisitor::getTag()); 1617aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose ID.AddPointer(StackFrame); 162aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks ID.AddBoolean(EnableNullFPSuppression); 1637aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose } 1647aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 1657aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// Adds a ReturnVisitor if the given statement represents a call that was 1667aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// inlined. 1677aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// 1687aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// This will search back through the ExplodedGraph, starting from the given 1697aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// node, looking for when the given statement was processed. If it turns out 1707aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// the statement is a call that was inlined, we add the visitor to the 1717aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose /// bug report, so it can print a note later. 1727aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S, 173aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BugReport &BR, 174aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bool InEnableNullFPSuppression) { 1757aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (!CallEvent::isCallStmt(S)) 1767aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose return; 1777aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 1787aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // First, find when we processed the statement. 1797aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose do { 1807a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>()) 1817aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (CEE->getCalleeContext()->getCallSite() == S) 1827aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose break; 1837a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>()) 1847aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (SP->getStmt() == S) 1857aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose break; 1867aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 1877aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose Node = Node->getFirstPred(); 1887aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose } while (Node); 1897aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 1907aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // Next, step over any post-statement checks. 1917a95de68c093991047ed8d339479ccad51b88663David Blaikie while (Node && Node->getLocation().getAs<PostStmt>()) 1927aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose Node = Node->getFirstPred(); 1938c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (!Node) 1948c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose return; 1957aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 1967aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // Finally, see if we inlined the call. 1978c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>(); 1988c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (!CEE) 1998c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose return; 2008c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 2018c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose const StackFrameContext *CalleeContext = CEE->getCalleeContext(); 2028c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (CalleeContext->getCallSite() != S) 2038c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose return; 2048c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 2058c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // Check the return value. 2068c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose ProgramStateRef State = Node->getState(); 2078c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose SVal RetVal = State->getSVal(S, Node->getLocationContext()); 2088c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 2098c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // Handle cases where a reference is returned and then immediately used. 2108c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (cast<Expr>(S)->isGLValue()) 2118c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (Optional<Loc> LValue = RetVal.getAs<Loc>()) 2128c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose RetVal = State->getSVal(*LValue); 2138c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 2148c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // See if the return value is NULL. If so, suppress the report. 2158c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose SubEngine *Eng = State->getStateManager().getOwningEngine(); 2168c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose assert(Eng && "Cannot file a bug report without an owning engine"); 2178c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose AnalyzerOptions &Options = Eng->getAnalysisManager().options; 2188c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 219aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bool EnableNullFPSuppression = false; 220aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()) 2218c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (Optional<Loc> RetLoc = RetVal.getAs<Loc>()) 222aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue(); 2238c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 2248c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose BR.markInteresting(CalleeContext); 225aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BR.addVisitor(new ReturnVisitor(CalleeContext, EnableNullFPSuppression)); 2267aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose } 2277aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2286a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose /// Returns true if any counter-suppression heuristics are enabled for 2296a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose /// ReturnVisitor. 2306a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose static bool hasCounterSuppression(AnalyzerOptions &Options) { 2316a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose return Options.shouldAvoidSuppressingNullArgumentPaths(); 2326a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 2337aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2346a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose PathDiagnosticPiece *visitNodeInitial(const ExplodedNode *N, 2356a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose const ExplodedNode *PrevN, 2366a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose BugReporterContext &BRC, 2376a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose BugReport &BR) { 2387aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // Only print a message at the interesting return statement. 2397aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (N->getLocationContext() != StackFrame) 2406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2417aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2427a95de68c093991047ed8d339479ccad51b88663David Blaikie Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>(); 2437aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (!SP) 2446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2457aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2467aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); 2477aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (!Ret) 2486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2497aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2507aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // Okay, we're at the right return statement, but do we have the return 2517aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // value available? 2527aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose ProgramStateRef State = N->getState(); 2537aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose SVal V = State->getSVal(Ret, StackFrame); 2547aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose if (V.isUnknownOrUndef()) 2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 2567aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2577aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose // Don't print any more notes after this one. 2586a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose Mode = Satisfied; 2597aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 2609abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose const Expr *RetE = Ret->getRetValue(); 2619abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose assert(RetE && "Tracking a return value for a void function"); 2629abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose 2639abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose // Handle cases where a reference is returned and then immediately used. 2649abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose Optional<Loc> LValue; 2659abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (RetE->isGLValue()) { 2669abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if ((LValue = V.getAs<Loc>())) { 2679abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose SVal RValue = State->getRawSVal(*LValue, RetE->getType()); 2689abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (RValue.getAs<DefinedSVal>()) 2699abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose V = RValue; 2709abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } 2719abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } 2729abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose 273deb8f5d533b7bcd962976ecdbc1464fe754b6de0Jordan Rose // Ignore aggregate rvalues. 274deb8f5d533b7bcd962976ecdbc1464fe754b6de0Jordan Rose if (V.getAs<nonloc::LazyCompoundVal>() || 275deb8f5d533b7bcd962976ecdbc1464fe754b6de0Jordan Rose V.getAs<nonloc::CompoundVal>()) 2766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 277deb8f5d533b7bcd962976ecdbc1464fe754b6de0Jordan Rose 2787aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose RetE = RetE->IgnoreParenCasts(); 2797aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 28053221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose // If we can't prove the return value is 0, just mark it interesting, and 28153221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose // make sure to track it into any further inner functions. 28285a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose if (!State->isNull(V).isConstrainedTrue()) { 2837aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose BR.markInteresting(V); 284aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks ReturnVisitor::addVisitorIfNecessary(N, RetE, BR, 285aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression); 2866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 28753221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose } 28853221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose 28953221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose // If we're returning 0, we should track where that 0 came from. 290aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bugreporter::trackNullOrUndefValue(N, RetE, BR, /*IsArg*/ false, 291aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression); 29253221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose 293b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose // Build an appropriate message based on the return value. 294b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose SmallString<64> Msg; 295b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose llvm::raw_svector_ostream Out(Msg); 296b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose 2975251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie if (V.getAs<Loc>()) { 2988c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // If we have counter-suppression enabled, make sure we keep visiting 2998c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // future nodes. We want to emit a path note as well, in case 300b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose // the report is resurrected as valid later on. 301b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose ExprEngine &Eng = BRC.getBugReporter().getEngine(); 3026a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose AnalyzerOptions &Options = Eng.getAnalysisManager().options; 303aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks if (EnableNullFPSuppression && hasCounterSuppression(Options)) 3048c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose Mode = MaybeUnsuppress; 305b9d4e5e3bb235f1149e99d3c833ff7cb3474c9f1Jordan Rose 30653221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose if (RetE->getType()->isObjCObjectPointerType()) 30753221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose Out << "Returning nil"; 30853221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose else 30953221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose Out << "Returning null pointer"; 31053221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose } else { 31153221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose Out << "Returning zero"; 3127aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose } 3137aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 3149abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (LValue) { 3159abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (const MemRegion *MR = LValue->getAsRegion()) { 3169abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (MR->canPrintPretty()) { 3179e2f5977a180ae927d05e844c65b8a7873be48a4Anna Zaks Out << " (reference to "; 3189abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose MR->printPretty(Out); 3199e2f5977a180ae927d05e844c65b8a7873be48a4Anna Zaks Out << ")"; 3209abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } 3219abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } 3229abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } else { 3239abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose // FIXME: We should have a more generalized location printing mechanism. 3249abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE)) 3259abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) 3269abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose Out << " (loaded from '" << *DD << "')"; 3279abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose } 3287aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 3297aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame); 3307aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose return new PathDiagnosticEventPiece(L, Out.str()); 3317aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose } 3326a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3338c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose PathDiagnosticPiece *visitNodeMaybeUnsuppress(const ExplodedNode *N, 3348c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose const ExplodedNode *PrevN, 3358c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose BugReporterContext &BRC, 3368c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose BugReport &BR) { 3378c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose#ifndef NDEBUG 3388c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose ExprEngine &Eng = BRC.getBugReporter().getEngine(); 3398c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose AnalyzerOptions &Options = Eng.getAnalysisManager().options; 3408c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose assert(hasCounterSuppression(Options)); 3418c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose#endif 3428c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 3436a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose // Are we at the entry node for this call? 3447a95de68c093991047ed8d339479ccad51b88663David Blaikie Optional<CallEnter> CE = N->getLocationAs<CallEnter>(); 3456a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose if (!CE) 3466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3476a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3486a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose if (CE->getCalleeContext() != StackFrame) 3496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3506a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3516a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose Mode = Satisfied; 3526a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3538c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // Don't automatically suppress a report if one of the arguments is 3548c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // known to be a null pointer. Instead, start tracking /that/ null 3558c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // value back to its origin. 3568c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose ProgramStateManager &StateMgr = BRC.getStateManager(); 3578c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose CallEventManager &CallMgr = StateMgr.getCallEventManager(); 3588c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 3598c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose ProgramStateRef State = N->getState(); 3608c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose CallEventRef<> Call = CallMgr.getCaller(StackFrame, State); 3618c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) { 3628c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>(); 3638c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (!ArgV) 3648c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose continue; 3658c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 3668c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose const Expr *ArgE = Call->getArgExpr(I); 3678c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose if (!ArgE) 3688c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose continue; 3698c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 3708c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // Is it possible for this argument to be non-null? 37185a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose if (!State->isNull(*ArgV).isConstrainedTrue()) 3728c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose continue; 3738c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 374aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks if (bugreporter::trackNullOrUndefValue(N, ArgE, BR, /*IsArg=*/true, 375aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression)) 3768c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose BR.removeInvalidation(ReturnVisitor::getTag(), StackFrame); 3778c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 3788c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // If we /can't/ track the null pointer, we should err on the side of 3798c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // false negatives, and continue towards marking this report invalid. 3808c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose // (We will still look at the other arguments, though.) 3816a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 3826a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3846a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 3856a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3866a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 3876a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose const ExplodedNode *PrevN, 3886a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose BugReporterContext &BRC, 389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BugReport &BR) override { 3906a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose switch (Mode) { 3916a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose case Initial: 3926a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose return visitNodeInitial(N, PrevN, BRC, BR); 3938c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose case MaybeUnsuppress: 3948c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose return visitNodeMaybeUnsuppress(N, PrevN, BRC, BR); 3956a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose case Satisfied: 3966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3976a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 3986a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 3996a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose llvm_unreachable("Invalid visit mode!"); 4006a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose } 4018c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose 4028c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, 4038c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose const ExplodedNode *N, 404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BugReport &BR) override { 405aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks if (EnableNullFPSuppression) 4068c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose BR.markInvalid(ReturnVisitor::getTag(), StackFrame); 4076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4088c84707fd0fbe9f6f7d17fadd5a9fe162dff8445Jordan Rose } 4097aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose}; 4107aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose} // end anonymous namespace 4117aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 4127aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 41350bbc165b063155cc23c360deb7b865502e068e2Anna Zaksvoid FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { 41450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks static int tag = 0; 41550bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.AddPointer(&tag); 41650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.AddPointer(R); 41750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.Add(V); 418aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks ID.AddBoolean(EnableNullFPSuppression); 41950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks} 4205350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 4212faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose/// Returns true if \p N represents the DeclStmt declaring and initializing 4222faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose/// \p VR. 4232faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rosestatic bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) { 4242faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose Optional<PostStmt> P = N->getLocationAs<PostStmt>(); 4252faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose if (!P) 4262faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose return false; 4272faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose 4282faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose const DeclStmt *DS = P->getStmtAs<DeclStmt>(); 4292faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose if (!DS) 4302faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose return false; 4312faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose 4322faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose if (DS->getSingleDecl() != VR->getDecl()) 4332faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose return false; 4342faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose 4352faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose const MemSpaceRegion *VarSpace = VR->getMemorySpace(); 4362faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace); 4372faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose if (!FrameSpace) { 4382faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose // If we ever directly evaluate global DeclStmts, this assertion will be 4392faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose // invalid, but this still seems preferable to silently accepting an 4402faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose // initialization that may be for a path-sensitive variable. 4412faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion"); 4422faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose return true; 4432faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose } 4442faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose 4452faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose assert(VR->getDecl()->hasLocalStorage()); 4462faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose const LocationContext *LCtx = N->getLocationContext(); 4472faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame(); 4482faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose} 4492faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose 450166b7bd43551964d65bcf4918f51a167b8374e2aJordan RosePathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, 451166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose const ExplodedNode *Pred, 452166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose BugReporterContext &BRC, 453166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose BugReport &BR) { 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4550dd15d78fb0c99faa5df724139ba4c16a9a345c6Ted Kremenek if (Satisfied) 4566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4570f2c907b2b5ee8896f5f0c51e35f80447b49b2c0Daniel Dunbar 4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const ExplodedNode *StoreSite = nullptr; 4596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Expr *InitE = nullptr; 46009f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose bool IsParam = false; 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 462166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose // First see if we reached the declaration of the region. 463166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 4642faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose if (isInitializationOfVar(Pred, VR)) { 4652faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose StoreSite = Pred; 4662faee99ab67105e834d11df7db80a78a3e3ed37bJordan Rose InitE = VR->getDecl()->getInit(); 4675350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 468166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose } 4691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 470610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks // If this is a post initializer expression, initializing the region, we 471610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks // should track the initializer expression. 472610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks if (Optional<PostInitializer> PIP = Pred->getLocationAs<PostInitializer>()) { 473610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue(); 474610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks if (FieldReg && FieldReg == R) { 475610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks StoreSite = Pred; 476610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks InitE = PIP->getInitializer()->getInit(); 477610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks } 478610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks } 479610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks 4806f4160828db75f36b22a204da202723c592644f3Jordan Rose // Otherwise, see if this is the store site: 4816f4160828db75f36b22a204da202723c592644f3Jordan Rose // (1) Succ has this binding and Pred does not, i.e. this is 4826f4160828db75f36b22a204da202723c592644f3Jordan Rose // where the binding first occurred. 4836f4160828db75f36b22a204da202723c592644f3Jordan Rose // (2) Succ has this binding and is a PostStore node for this region, i.e. 4846f4160828db75f36b22a204da202723c592644f3Jordan Rose // the same binding was re-assigned here. 485166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (!StoreSite) { 486166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (Succ->getState()->getSVal(R) != V) 4876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4886f4160828db75f36b22a204da202723c592644f3Jordan Rose 4896f4160828db75f36b22a204da202723c592644f3Jordan Rose if (Pred->getState()->getSVal(R) == V) { 4906f4160828db75f36b22a204da202723c592644f3Jordan Rose Optional<PostStore> PS = Succ->getLocationAs<PostStore>(); 4916f4160828db75f36b22a204da202723c592644f3Jordan Rose if (!PS || PS->getLocationValue() != R) 4926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 4936f4160828db75f36b22a204da202723c592644f3Jordan Rose } 4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 495166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose StoreSite = Succ; 4967aba1171b32265b2206f3fa8f8886953051b58f5Jordan Rose 497166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose // If this is an assignment expression, we can track the value 498166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose // being assigned. 4997a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>()) 500166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) 501166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (BO->isAssignmentOp()) 502166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose InitE = BO->getRHS(); 50385e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose 50485e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose // If this is a call entry, the variable should be a parameter. 50585e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose // FIXME: Handle CXXThisRegion as well. (This is not a priority because 50685e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose // 'this' should never be NULL, but this visitor isn't just for NULL and 50785e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose // UndefinedVal.) 5087a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) { 5096c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 5106c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 5116c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek 5126c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek ProgramStateManager &StateMgr = BRC.getStateManager(); 5136c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek CallEventManager &CallMgr = StateMgr.getCallEventManager(); 5146c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek 5156c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), 5166c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek Succ->getState()); 5176c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); 5186c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek IsParam = true; 5196c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } 52085e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose } 5216022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks 5226022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // If this is a CXXTempObjectRegion, the Expr responsible for its creation 5236022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // is wrapped inside of it. 5246022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R)) 5256022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks InitE = TmpR->getExpr(); 52650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 528166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (!StoreSite) 5296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 5300dd15d78fb0c99faa5df724139ba4c16a9a345c6Ted Kremenek Satisfied = true; 531166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose 53253221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose // If we have an expression that provided the value, try to track where it 53353221da865144db0ba6bd89ab30bcf81de0fe5d2Jordan Rose // came from. 534166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose if (InitE) { 5357f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks if (V.isUndef() || 5367f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) { 53709f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose if (!IsParam) 53809f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose InitE = InitE->IgnoreParenCasts(); 539aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam, 540aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression); 54109f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } else { 54209f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), 543aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BR, EnableNullFPSuppression); 54409f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } 545166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose } 546166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose 547166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose // Okay, we've found the binding. Emit an appropriate message. 548f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> sbuf; 54950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks llvm::raw_svector_ostream os(sbuf); 5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5517a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) { 5525846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek const Stmt *S = PS->getStmt(); 5536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *action = nullptr; 5545846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek const DeclStmt *DS = dyn_cast<DeclStmt>(S); 5555846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek const VarRegion *VR = dyn_cast<VarRegion>(R); 5565846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 5575846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (DS) { 5588713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks action = R->canPrintPretty() ? "initialized to " : 5598713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks "Initializing to "; 5605846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } else if (isa<BlockExpr>(S)) { 5618713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks action = R->canPrintPretty() ? "captured by block as " : 56282dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks "Captured by block as "; 5635846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (VR) { 5645846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // See if we can get the BlockVarRegion. 5655846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek ProgramStateRef State = StoreSite->getState(); 5665846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek SVal V = State->getSVal(S, PS->getLocationContext()); 5675846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (const BlockDataRegion *BDR = 5685846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { 5695846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { 5700dd15d78fb0c99faa5df724139ba4c16a9a345c6Ted Kremenek if (Optional<KnownSVal> KV = 5710dd15d78fb0c99faa5df724139ba4c16a9a345c6Ted Kremenek State->getSVal(OriginalR).getAs<KnownSVal>()) 572aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BR.addVisitor(new FindLastStoreBRVisitor(*KV, OriginalR, 573aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression)); 5745846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 5755846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 5765350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 5775846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 5785846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 5795846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (action) { 5808713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks if (R->canPrintPretty()) { 5818713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks R->printPretty(os); 5828713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << " "; 5838713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks } 5848713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks 5855251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie if (V.getAs<loc::ConcreteInt>()) { 5865350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek bool b = false; 5875350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek if (R->isBoundable()) { 5889697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 589018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu if (TR->getValueType()->isObjCObjectPointerType()) { 5905846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek os << action << "nil"; 5915350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek b = true; 5925350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 5935350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 5945350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 5951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5965350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek if (!b) 5975846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek os << action << "a null pointer value"; 598dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie } else if (Optional<nonloc::ConcreteInt> CVal = 5995251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie V.getAs<nonloc::ConcreteInt>()) { 6005251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie os << action << CVal->getValue(); 601592362b46ad69db0db0988e7f9d8cbe647510bddTed Kremenek } 6025846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek else if (DS) { 6035846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (V.isUndef()) { 6045846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (isa<VarRegion>(R)) { 6055846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 6068713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks if (VD->getInit()) { 6078713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << (R->canPrintPretty() ? "initialized" : "Initializing") 6088713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks << " to a garbage value"; 6098713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks } else { 6108713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << (R->canPrintPretty() ? "declared" : "Declaring") 6118713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks << " without an initial value"; 6128713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks } 6135846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 6145846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 6155846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek else { 61682dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << (R->canPrintPretty() ? "initialized" : "Initialized") 6178713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks << " here"; 61850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 619685379965c1b105ce89cf4f6c60810932b7f4d0dJordan Rose } 6205350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 6217a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (StoreSite->getLocation().getAs<CallEnter>()) { 6226c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 6236c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); 62485e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose 6256c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "Passing "; 62685e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose 6276c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek if (V.getAs<loc::ConcreteInt>()) { 6286c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek if (Param->getType()->isObjCObjectPointerType()) 6296c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "nil object reference"; 6306c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek else 6316c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "null pointer value"; 6326c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } else if (V.isUndef()) { 6336c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "uninitialized value"; 6346c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } else if (Optional<nonloc::ConcreteInt> CI = 6356c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek V.getAs<nonloc::ConcreteInt>()) { 6366c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "the value " << CI->getValue(); 6376c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } else { 6386c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek os << "value"; 6396c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } 64085e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose 6416c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek // Printed parameter indexes are 1-based, not 0-based. 6426c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek unsigned Idx = Param->getFunctionScopeIndex() + 1; 6438713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter"; 6448713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks if (R->canPrintPretty()) { 6458713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << " "; 6468713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks R->printPretty(os); 6478713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks } 6486c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek } 64950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (os.str().empty()) { 6525251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie if (V.getAs<loc::ConcreteInt>()) { 65350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks bool b = false; 65450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (R->isBoundable()) { 65550bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 65650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (TR->getValueType()->isObjCObjectPointerType()) { 6578713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << "nil object reference stored"; 65850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks b = true; 65950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 66050bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 66150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 66282dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks if (!b) { 66382dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks if (R->canPrintPretty()) 66482dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Null pointer value stored"; 66582dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks else 66682dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Storing null pointer value"; 66782dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks } 66882dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks 66982dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks } else if (V.isUndef()) { 67082dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks if (R->canPrintPretty()) 67182dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Uninitialized value stored"; 67282dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks else 67382dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Storing uninitialized value"; 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 675dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie } else if (Optional<nonloc::ConcreteInt> CV = 6765251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie V.getAs<nonloc::ConcreteInt>()) { 67782dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks if (R->canPrintPretty()) 67882dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "The value " << CV->getValue() << " is assigned"; 67982dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks else 68082dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Assigning " << CV->getValue(); 6811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68282dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks } else { 68382dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks if (R->canPrintPretty()) 68482dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Value assigned"; 68582dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks else 68682dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks os << "Assigning value"; 68782dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks } 68882dd4396fcd2517d06382b7170f393d1b6351c7fAnna Zaks 6898713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks if (R->canPrintPretty()) { 6908713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks os << " to "; 6918713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks R->printPretty(os); 6928713e1a5c3f6658d54061e176b5baa9fadf14675Anna Zaks } 6935350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 6945350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 6954fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks // Construct a new PathDiagnosticPiece. 696166b7bd43551964d65bcf4918f51a167b8374e2aJordan Rose ProgramPoint P = StoreSite->getLocation(); 69785e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose PathDiagnosticLocation L; 6986c5038cf8486d92ae53bf4513141bd40a5ae0734Ted Kremenek if (P.getAs<CallEnter>() && InitE) 69985e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose L = PathDiagnosticLocation(InitE, BRC.getSourceManager(), 70085e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose P.getLocationContext()); 701636478e288b88396d860f6b01b48b47953e3d5e9Anna Zaks 702636478e288b88396d860f6b01b48b47953e3d5e9Anna Zaks if (!L.isValid() || !L.asLocation().isValid()) 70385e99373835fe1b4cec624bc48dc8dfe14c2a783Jordan Rose L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); 704636478e288b88396d860f6b01b48b47953e3d5e9Anna Zaks 705636478e288b88396d860f6b01b48b47953e3d5e9Anna Zaks if (!L.isValid() || !L.asLocation().isValid()) 7066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 707636478e288b88396d860f6b01b48b47953e3d5e9Anna Zaks 70850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks return new PathDiagnosticEventPiece(L, os.str()); 70950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks} 7100f2c907b2b5ee8896f5f0c51e35f80447b49b2c0Daniel Dunbar 71150bbc165b063155cc23c360deb7b865502e068e2Anna Zaksvoid TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { 71250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks static int tag = 0; 71350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.AddPointer(&tag); 71450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.AddBoolean(Assumption); 71550bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ID.Add(Constraint); 71650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks} 7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 718b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek/// Return the tag associated with this visitor. This tag will be used 719b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek/// to make all PathDiagnosticPieces created by this visitor. 720b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekconst char *TrackConstraintBRVisitor::getTag() { 721b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return "TrackConstraintBRVisitor"; 722b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 723b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 72485a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rosebool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const { 72585a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose if (IsZeroCheck) 72685a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose return N->getState()->isNull(Constraint).isUnderconstrained(); 727ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return (bool)N->getState()->assume(Constraint, !Assumption); 72885a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose} 72985a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose 73050bbc165b063155cc23c360deb7b865502e068e2Anna ZaksPathDiagnosticPiece * 73150bbc165b063155cc23c360deb7b865502e068e2Anna ZaksTrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, 73250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const ExplodedNode *PrevN, 73350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReporterContext &BRC, 73450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReport &BR) { 73585a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose if (IsSatisfied) 7366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 7371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7385b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks // Start tracking after we see the first state in which the value is 7395b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks // constrained. 7405b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks if (!IsTrackingTurnedOn) 7415b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks if (!isUnderconstrained(N)) 7425b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks IsTrackingTurnedOn = true; 7435b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks if (!IsTrackingTurnedOn) 7446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 7455b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks 74650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // Check if in the previous state it was feasible for this constraint 74750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // to *not* be true. 74885a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose if (isUnderconstrained(PrevN)) { 7491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75085a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose IsSatisfied = true; 7511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // As a sanity check, make sure that the negation of the constraint 75350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // was infeasible in the current state. If it is feasible, we somehow 75450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // missed the transition point. 7555b90ae7ba05a10a81f107ec1635deb1bd7292936Anna Zaks assert(!isUnderconstrained(N)); 7561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 75750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // We found the transition point for the constraint. We now need to 75850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // pretty-print the constraint. (work-in-progress) 75985a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose SmallString<64> sbuf; 76085a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose llvm::raw_svector_ostream os(sbuf); 7611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7625251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie if (Constraint.getAs<Loc>()) { 76350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks os << "Assuming pointer value is "; 76450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks os << (Assumption ? "non-null" : "null"); 76550bbc165b063155cc23c360deb7b865502e068e2Anna Zaks } 7661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 76750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (os.str().empty()) 7686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 76950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks 7704fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks // Construct a new PathDiagnosticPiece. 77150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks ProgramPoint P = N->getLocation(); 7721531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks PathDiagnosticLocation L = 7731531bb0c69d9afff6a6434e4cadf345eb628b287Anna Zaks PathDiagnosticLocation::create(P, BRC.getSourceManager()); 7744fdf97bf51d2a156cec3232efd6dae110aa02aa0Anna Zaks if (!L.isValid()) 7756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 7766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 777b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek PathDiagnosticEventPiece *X = new PathDiagnosticEventPiece(L, os.str()); 778b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek X->setTag(getTag()); 779b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return X; 7801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 7815350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 7826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 7835350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek} 7845350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek 785cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna ZaksSuppressInlineDefensiveChecksVisitor:: 786cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna ZaksSuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) 787a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks : V(Value), IsSatisfied(false), IsTrackingTurnedOn(false) { 788f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks 789f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks // Check if the visitor is disabled. 790f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks SubEngine *Eng = N->getState()->getStateManager().getOwningEngine(); 791f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks assert(Eng && "Cannot file a bug report without an owning engine"); 792f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks AnalyzerOptions &Options = Eng->getAnalysisManager().options; 793f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks if (!Options.shouldSuppressInlinedDefensiveChecks()) 794f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks IsSatisfied = true; 795f8ba81e8bbc4d0d424c3b4c3581a9467e972c4deAnna Zaks 796a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks assert(N->getState()->isNull(V).isConstrainedTrue() && 797a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks "The visitor only tracks the cases where V is constrained to 0"); 798cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks} 799cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 800cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaksvoid SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const { 801cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks static int id = 0; 802cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks ID.AddPointer(&id); 803cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks ID.Add(V); 804cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks} 805cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 806cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaksconst char *SuppressInlineDefensiveChecksVisitor::getTag() { 807cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks return "IDCVisitor"; 808cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks} 809cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 810cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna ZaksPathDiagnosticPiece * 8110415998dd77986630efe8f1aed633519cc41e1f3Anna ZaksSuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, 8120415998dd77986630efe8f1aed633519cc41e1f3Anna Zaks const ExplodedNode *Pred, 813cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks BugReporterContext &BRC, 814cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks BugReport &BR) { 815cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks if (IsSatisfied) 8166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 817713e07591995d761f65c7132289dce003a29870fAnna Zaks 818a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks // Start tracking after we see the first state in which the value is null. 819a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks if (!IsTrackingTurnedOn) 820a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks if (Succ->getState()->isNull(V).isConstrainedTrue()) 821a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks IsTrackingTurnedOn = true; 822a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks if (!IsTrackingTurnedOn) 8236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 824a4bb4f6ca8dd31ad96cb9526a5abe1273f18ff40Anna Zaks 825cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks // Check if in the previous state it was feasible for this value 826cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks // to *not* be null. 827810169e7a1f858a787d2db050deebaee7e10c97fAnna Zaks if (!Pred->getState()->isNull(V).isConstrainedTrue()) { 828cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks IsSatisfied = true; 829cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 830810169e7a1f858a787d2db050deebaee7e10c97fAnna Zaks assert(Succ->getState()->isNull(V).isConstrainedTrue()); 831cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 8320415998dd77986630efe8f1aed633519cc41e1f3Anna Zaks // Check if this is inlined defensive checks. 8330415998dd77986630efe8f1aed633519cc41e1f3Anna Zaks const LocationContext *CurLC =Succ->getLocationContext(); 834cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext(); 835cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) 836cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks BR.markInvalid("Suppress IDC", CurLC); 837cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks } 8386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 839cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks} 840cc5dbdae70c6eb2423921f52a35ba4686d2969cfAnna Zaks 8416022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaksstatic const MemRegion *getLocationRegionIfReference(const Expr *E, 8426022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks const ExplodedNode *N) { 8436022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) { 8446022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 8456022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (!VD->getType()->isReferenceType()) 8466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 8476022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks ProgramStateManager &StateMgr = N->getState()->getStateManager(); 8486022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks MemRegionManager &MRMgr = StateMgr.getRegionManager(); 8496022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks return MRMgr.getVarRegion(VD, N->getLocationContext()); 8506022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks } 8516022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks } 8526022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks 8536022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // FIXME: This does not handle other kinds of null references, 8546022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // for example, references from FieldRegions: 8556022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // struct Wrapper { int &ref; }; 8566022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // Wrapper w = { *(int *)0 }; 8576022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // w.ref = 1; 8586022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks 8596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 8606022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks} 8616022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks 862cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaksstatic const Expr *peelOffOuterExpr(const Expr *Ex, 8631533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks const ExplodedNode *N) { 864cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks Ex = Ex->IgnoreParenCasts(); 865cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex)) 866cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks return peelOffOuterExpr(EWC->getSubExpr(), N); 867cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex)) 868cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks return peelOffOuterExpr(OVE->getSourceExpr(), N); 869cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks 870cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks // Peel off the ternary operator. 871cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) { 872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Find a node where the branching occurred and find out which branch 873702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks // we took (true/false) by looking at the ExplodedGraph. 874702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks const ExplodedNode *NI = N; 875cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks do { 876702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks ProgramPoint ProgPoint = NI->getLocation(); 877702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) { 878702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks const CFGBlock *srcBlk = BE->getSrc(); 879702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks if (const Stmt *term = srcBlk->getTerminator()) { 880702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks if (term == CO) { 881702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst()); 882702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks if (TookTrueBranch) 883702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks return peelOffOuterExpr(CO->getTrueExpr(), N); 884702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks else 885702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks return peelOffOuterExpr(CO->getFalseExpr(), N); 886702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks } 887702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks } 888cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks } 889702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks NI = NI->getFirstPred(); 890702077f14100f2d7acdb12ad49b53e64efc37d72Anna Zaks } while (NI); 891dc9c160dede7e2f5cc11755db6aaa57e7fccbcecAnna Zaks } 892cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks return Ex; 8931533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks} 8941533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks 8951533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaksbool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, 8961533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks const Stmt *S, 897aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BugReport &report, bool IsArg, 898aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bool EnableNullFPSuppression) { 8991533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks if (!S || !N) 9001533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks return false; 9011533833e21ae5b3f5f39b168b3fbac109ee77008Anna Zaks 902cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks if (const Expr *Ex = dyn_cast<Expr>(S)) { 903cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks Ex = Ex->IgnoreParenCasts(); 904cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks const Expr *PeeledEx = peelOffOuterExpr(Ex, N); 905cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks if (Ex != PeeledEx) 906cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks S = PeeledEx; 907cabc3fddae63f5eb3bd44bdecce7a3fbd69421a9Anna Zaks } 9080415998dd77986630efe8f1aed633519cc41e1f3Anna Zaks 9096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Expr *Inner = nullptr; 9100183768813658d419e3124b576744b03ec8e9b55Jordan Rose if (const Expr *Ex = dyn_cast<Expr>(S)) { 9110183768813658d419e3124b576744b03ec8e9b55Jordan Rose Ex = Ex->IgnoreParenCasts(); 91277b72231a0316509cc939b052be35fafce606567Jordan Rose if (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex)) 91377b72231a0316509cc939b052be35fafce606567Jordan Rose Inner = Ex; 9140183768813658d419e3124b576744b03ec8e9b55Jordan Rose } 9150183768813658d419e3124b576744b03ec8e9b55Jordan Rose 916dcd6224911e234ab3657b7d0b79a2add1ae4fdd8Jordan Rose if (IsArg && !Inner) { 9177a95de68c093991047ed8d339479ccad51b88663David Blaikie assert(N->getLocation().getAs<CallEnter>() && "Tracking arg but not at call"); 91809f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } else { 91909f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose // Walk through nodes until we get one that matches the statement exactly. 9200183768813658d419e3124b576744b03ec8e9b55Jordan Rose // Alternately, if we hit a known lvalue for the statement, we know we've 9210183768813658d419e3124b576744b03ec8e9b55Jordan Rose // gone too far (though we can likely track the lvalue better anyway). 92209f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose do { 92309f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose const ProgramPoint &pp = N->getLocation(); 9244de4715ad02aa8c9437a9e0e2854a0ccc71a3188Anna Zaks if (Optional<StmtPoint> ps = pp.getAs<StmtPoint>()) { 92577b72231a0316509cc939b052be35fafce606567Jordan Rose if (ps->getStmt() == S || ps->getStmt() == Inner) 92609f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose break; 9277a95de68c093991047ed8d339479ccad51b88663David Blaikie } else if (Optional<CallExitEnd> CEE = pp.getAs<CallExitEnd>()) { 92877b72231a0316509cc939b052be35fafce606567Jordan Rose if (CEE->getCalleeContext()->getCallSite() == S || 92977b72231a0316509cc939b052be35fafce606567Jordan Rose CEE->getCalleeContext()->getCallSite() == Inner) 93009f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose break; 93109f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } 93209f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose N = N->getFirstPred(); 93309f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } while (N); 934882998923889a2fcce9b49696506c499e22cf38fTed Kremenek 93509f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose if (!N) 9366a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose return false; 93709f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose } 938882998923889a2fcce9b49696506c499e22cf38fTed Kremenek 9398bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = N->getState(); 9401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94184e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks // The message send could be nil due to the receiver being nil. 94284e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks // At this point in the path, the receiver should be live since we are at the 94384e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks // message send expr. If it is nil, start tracking it. 94484e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(S, N)) 945dcd6224911e234ab3657b7d0b79a2add1ae4fdd8Jordan Rose trackNullOrUndefValue(N, Receiver, report, false, EnableNullFPSuppression); 94684e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks 94784e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks 94884e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks // See if the expression we're interested refers to a variable. 949364b9f95fa47b0ca7f1cc694195f7a9953652f81Jordan Rose // If so, we can track both its contents and constraints on its value. 95077b72231a0316509cc939b052be35fafce606567Jordan Rose if (Inner && ExplodedGraph::isInterestingLValueExpr(Inner)) { 9516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const MemRegion *R = nullptr; 9520183768813658d419e3124b576744b03ec8e9b55Jordan Rose 9536022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // Find the ExplodedNode where the lvalue (the value of 'Ex') 9546022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // was computed. We need this for getting the location value. 9556022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks const ExplodedNode *LVNode = N; 9566022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks while (LVNode) { 9576022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (Optional<PostStmt> P = LVNode->getLocation().getAs<PostStmt>()) { 9586022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (P->getStmt() == Inner) 9596022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks break; 96043b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek } 9616022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks LVNode = LVNode->getFirstPred(); 9620183768813658d419e3124b576744b03ec8e9b55Jordan Rose } 9636022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks assert(LVNode && "Unable to find the lvalue node."); 9646022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks ProgramStateRef LVState = LVNode->getState(); 9656022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext()); 9666022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks 9676022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (LVState->isNull(LVal).isConstrainedTrue()) { 9686022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // In case of C++ references, we want to differentiate between a null 9696022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // reference and reference to null pointer. 9706022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // If the LVal is null, check if we are dealing with null reference. 9716022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // For those, we want to track the location of the reference. 9726022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) 9736022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks R = RR; 9746022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks } else { 9756022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks R = LVState->getSVal(Inner, LVNode->getLocationContext()).getAsRegion(); 97643b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek 9776022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // If this is a C++ reference to a null pointer, we are tracking the 9786022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // pointer. In additon, we should find the store at which the reference 9796022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks // got initialized. 9806022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) { 9816022c4e17c0d2ad9c43ef6bc830d394b670a4705Anna Zaks if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>()) 982aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks report.addVisitor(new FindLastStoreBRVisitor(*KV, RR, 983aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression)); 98443b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek } 9850183768813658d419e3124b576744b03ec8e9b55Jordan Rose } 98643b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek 9870183768813658d419e3124b576744b03ec8e9b55Jordan Rose if (R) { 9880183768813658d419e3124b576744b03ec8e9b55Jordan Rose // Mark both the variable region and its contents as interesting. 9894b69feb6d90eb120d04f5d54f6b28cc295a46098Anna Zaks SVal V = LVState->getRawSVal(loc::MemRegionVal(R)); 99009f7bf14d25bdc55cb715bc8d40600906848a409Jordan Rose 9910183768813658d419e3124b576744b03ec8e9b55Jordan Rose report.markInteresting(R); 9920183768813658d419e3124b576744b03ec8e9b55Jordan Rose report.markInteresting(V); 9930183768813658d419e3124b576744b03ec8e9b55Jordan Rose report.addVisitor(new UndefOrNullArgVisitor(R)); 994685379965c1b105ce89cf4f6c60810932b7f4d0dJordan Rose 9950183768813658d419e3124b576744b03ec8e9b55Jordan Rose // If the contents are symbolic, find out when they became null. 9968ef064d53fb33b5a8f8743bcbb0a2fd5c3e97be1Anna Zaks if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true)) { 9970183768813658d419e3124b576744b03ec8e9b55Jordan Rose BugReporterVisitor *ConstraintTracker = 9980183768813658d419e3124b576744b03ec8e9b55Jordan Rose new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false); 9990183768813658d419e3124b576744b03ec8e9b55Jordan Rose report.addVisitor(ConstraintTracker); 10007f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks } 10010183768813658d419e3124b576744b03ec8e9b55Jordan Rose 10027f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks // Add visitor, which will suppress inline defensive checks. 10037f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) { 10047f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks if (!DV->isZeroConstant() && 10057f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks LVState->isNull(*DV).isConstrainedTrue() && 10067f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks EnableNullFPSuppression) { 10070183768813658d419e3124b576744b03ec8e9b55Jordan Rose BugReporterVisitor *IDCSuppressor = 10087f79b78351af03a392ee16d8ec557d47746c33c6Anna Zaks new SuppressInlineDefensiveChecksVisitor(*DV, 10094b69feb6d90eb120d04f5d54f6b28cc295a46098Anna Zaks LVNode); 10100183768813658d419e3124b576744b03ec8e9b55Jordan Rose report.addVisitor(IDCSuppressor); 1011685379965c1b105ce89cf4f6c60810932b7f4d0dJordan Rose } 10125350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 10130183768813658d419e3124b576744b03ec8e9b55Jordan Rose 10140183768813658d419e3124b576744b03ec8e9b55Jordan Rose if (Optional<KnownSVal> KV = V.getAs<KnownSVal>()) 1015aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks report.addVisitor(new FindLastStoreBRVisitor(*KV, R, 1016aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression)); 10170183768813658d419e3124b576744b03ec8e9b55Jordan Rose return true; 10185350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 10195350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 10201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102143b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek // If the expression is not an "lvalue expression", we can still 102243b82b823a6113fdbee54243b280db9c55ef72cbTed Kremenek // track the constraints on its contents. 10235eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); 10241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10259abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose // If the value came from an inlined function call, we should at least make 10269abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose // sure that function isn't pruned in our output. 10279abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose if (const Expr *E = dyn_cast<Expr>(S)) 10289abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose S = E->IgnoreParenCasts(); 1029aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks 1030aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks ReturnVisitor::addVisitorIfNecessary(N, S, report, EnableNullFPSuppression); 10319abf1b4577b75ffcc46afbdfb55de334f68f05c0Jordan Rose 10325350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek // Uncomment this to find cases where we aren't properly getting the 10335350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek // base value that was dereferenced. 10345350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek // assert(!V.isUnknownOrUndef()); 10355350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek // Is it a symbolic value? 1036dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie if (Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) { 1037d91696e8680bbe89df1076fded1bc54104526060Anna Zaks // At this point we are dealing with the region's LValue. 1038d91696e8680bbe89df1076fded1bc54104526060Anna Zaks // However, if the rvalue is a symbolic region, we should track it as well. 1039441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks // Try to use the correct type when looking up the value. 1040441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks SVal RVal; 1041441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks if (const Expr *E = dyn_cast<Expr>(S)) 1042441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks RVal = state->getRawSVal(L.getValue(), E->getType()); 1043441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks else 1044441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks RVal = state->getSVal(L->getRegion()); 1045441625e6c7f8bf58e62a284ae1f855dafde31ec2Anna Zaks 1046d91696e8680bbe89df1076fded1bc54104526060Anna Zaks const MemRegion *RegionRVal = RVal.getAsRegion(); 1047522fc21f3adc647817edc8017e6928a64c96899bAnna Zaks report.addVisitor(new UndefOrNullArgVisitor(L->getRegion())); 1048522fc21f3adc647817edc8017e6928a64c96899bAnna Zaks 1049d91696e8680bbe89df1076fded1bc54104526060Anna Zaks if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { 1050d91696e8680bbe89df1076fded1bc54104526060Anna Zaks report.markInteresting(RegionRVal); 1051d91696e8680bbe89df1076fded1bc54104526060Anna Zaks report.addVisitor(new TrackConstraintBRVisitor( 1052d91696e8680bbe89df1076fded1bc54104526060Anna Zaks loc::MemRegionVal(RegionRVal), false)); 10535350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 10545350066e7b19d17a5b137caa6c039ab9626dbfa5Ted Kremenek } 10556a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose 10566a329ee7567cf3267ffab2bc755ea8c773d967e7Jordan Rose return true; 105750bbc165b063155cc23c360deb7b865502e068e2Anna Zaks} 105894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 105984e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaksconst Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S, 106084e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks const ExplodedNode *N) { 1061aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S); 1062aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks if (!ME) 10636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 106484e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks if (const Expr *Receiver = ME->getInstanceReceiver()) { 106584e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks ProgramStateRef state = N->getState(); 106684e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks SVal V = state->getSVal(Receiver, N->getLocationContext()); 106784e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks if (state->isNull(V).isConstrainedTrue()) 106884e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks return Receiver; 106984e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks } 10706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 107194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek} 1072ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek 107350bbc165b063155cc23c360deb7b865502e068e2Anna ZaksPathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, 107450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const ExplodedNode *PrevN, 107550bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReporterContext &BRC, 107650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReport &BR) { 10774a49df3be929d442535d6721ab8a2bbc8a7cd528Anna Zaks Optional<PreStmt> P = N->getLocationAs<PreStmt>(); 107850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (!P) 10796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1080aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks 108162fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek const Stmt *S = P->getStmt(); 108262fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek const Expr *Receiver = getNilReceiver(S, N); 108350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (!Receiver) 10846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 108585a92cfa52ddf4c45fe2baca4d7fea0bdc5ed103Jordan Rose 108662fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek llvm::SmallString<256> Buf; 108762fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek llvm::raw_svector_ostream OS(Buf); 108862fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek 108962fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) { 1090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "'"; 1091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ME->getSelector().print(OS); 1092651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "' not called"; 109362fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek } 109462fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek else { 109562fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek OS << "No method is called"; 109662fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek } 109762fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek OS << " because the receiver is nil"; 109862fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek 109950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // The receiver was nil, and hence the method was skipped. 110050bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // Register a BugReporterVisitor to issue a message telling us how 110150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // the receiver was null. 1102aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bugreporter::trackNullOrUndefValue(N, Receiver, BR, /*IsArg*/ false, 110384e8a960ad76b3c7ca550b4cc92a1b90ed16d5c1Anna Zaks /*EnableNullFPSuppression*/ false); 110450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // Issue a message saying that the method was skipped. 1105220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks PathDiagnosticLocation L(Receiver, BRC.getSourceManager(), 1106220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks N->getLocationContext()); 110762fba4f08af16ff17b5cbe8816061349504317e4Ted Kremenek return new PathDiagnosticEventPiece(L, OS.str()); 1108ff7f736211070be873df0a345295fd1453ee7c50Ted Kremenek} 11092bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11108e6431adab313e283a992698f6fc7afe62420999Anna Zaks// Registers every VarDecl inside a Stmt with a last store visitor. 111150bbc165b063155cc23c360deb7b865502e068e2Anna Zaksvoid FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, 1112aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks const Stmt *S, 1113aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks bool EnableNullFPSuppression) { 11148e6431adab313e283a992698f6fc7afe62420999Anna Zaks const ExplodedNode *N = BR.getErrorNode(); 11152bbbe50dbaa0bf231c16333b335304655deeb26bTom Care std::deque<const Stmt *> WorkList; 11162bbbe50dbaa0bf231c16333b335304655deeb26bTom Care WorkList.push_back(S); 11172bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11182bbbe50dbaa0bf231c16333b335304655deeb26bTom Care while (!WorkList.empty()) { 11192bbbe50dbaa0bf231c16333b335304655deeb26bTom Care const Stmt *Head = WorkList.front(); 11202bbbe50dbaa0bf231c16333b335304655deeb26bTom Care WorkList.pop_front(); 11212bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11228bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = N->getState(); 11238e6431adab313e283a992698f6fc7afe62420999Anna Zaks ProgramStateManager &StateMgr = state->getStateManager(); 11242bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11252bbbe50dbaa0bf231c16333b335304655deeb26bTom Care if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { 11262bbbe50dbaa0bf231c16333b335304655deeb26bTom Care if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 11272bbbe50dbaa0bf231c16333b335304655deeb26bTom Care const VarRegion *R = 11282bbbe50dbaa0bf231c16333b335304655deeb26bTom Care StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); 11292bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11302bbbe50dbaa0bf231c16333b335304655deeb26bTom Care // What did we load? 11315eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal V = state->getSVal(S, N->getLocationContext()); 11322bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11335251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) { 113450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks // Register a new visitor with the BugReport. 1135aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks BR.addVisitor(new FindLastStoreBRVisitor(V.castAs<KnownSVal>(), R, 1136aabb4c5eacca6d78ef778f33ec5cd4c755d71a39Anna Zaks EnableNullFPSuppression)); 11372bbbe50dbaa0bf231c16333b335304655deeb26bTom Care } 11382bbbe50dbaa0bf231c16333b335304655deeb26bTom Care } 11392bbbe50dbaa0bf231c16333b335304655deeb26bTom Care } 11402bbbe50dbaa0bf231c16333b335304655deeb26bTom Care 11412bbbe50dbaa0bf231c16333b335304655deeb26bTom Care for (Stmt::const_child_iterator I = Head->child_begin(); 11422bbbe50dbaa0bf231c16333b335304655deeb26bTom Care I != Head->child_end(); ++I) 11432bbbe50dbaa0bf231c16333b335304655deeb26bTom Care WorkList.push_back(*I); 11442bbbe50dbaa0bf231c16333b335304655deeb26bTom Care } 11452bbbe50dbaa0bf231c16333b335304655deeb26bTom Care} 1146993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1147993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek//===----------------------------------------------------------------------===// 1148993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek// Visitor that tries to report interesting diagnostics from conditions. 1149993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek//===----------------------------------------------------------------------===// 1150b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 1151b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek/// Return the tag associated with this visitor. This tag will be used 1152b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek/// to make all PathDiagnosticPieces created by this visitor. 1153b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenekconst char *ConditionBRVisitor::getTag() { 1154b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek return "ConditionBRVisitor"; 1155b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek} 1156b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek 115750bbc165b063155cc23c360deb7b865502e068e2Anna ZaksPathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N, 115850bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const ExplodedNode *Prev, 115950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReporterContext &BRC, 116050bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReport &BR) { 1161c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR); 1162b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (piece) { 1163b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek piece->setTag(getTag()); 1164b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek if (PathDiagnosticEventPiece *ev=dyn_cast<PathDiagnosticEventPiece>(piece)) 1165b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek ev->setPrunable(true, /* override */ false); 1166b85cce094887ab5cf1c47acfe306e2fb1d3cfbb1Ted Kremenek } 1167c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek return piece; 1168c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek} 1169c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek 1170c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted KremenekPathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, 1171c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek const ExplodedNode *Prev, 1172c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek BugReporterContext &BRC, 1173c89f4b05721f53cfbaf32fc0c4919a4616e68440Ted Kremenek BugReport &BR) { 1174993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 117522505ef15e32db31a4f834a387cf73a913bc8f66Ted Kremenek ProgramPoint progPoint = N->getLocation(); 11768bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CurrentState = N->getState(); 11778bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef PrevState = Prev->getState(); 1178681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1179681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // Compare the GDMs of the state, because that is where constraints 1180681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // are managed. Note that ensure that we only look at nodes that 1181681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // were generated by the analyzer engine proper, not checkers. 1182681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (CurrentState->getGDM().getRoot() == 1183681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek PrevState->getGDM().getRoot()) 11846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 11856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1186993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek // If an assumption was made on a branch, it should be caught 1187993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek // here by looking at the state transition. 11887a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) { 1189681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek const CFGBlock *srcBlk = BE->getSrc(); 1190681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (const Stmt *term = srcBlk->getTerminator()) 119176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); 11926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1193681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1194681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 11957a95de68c093991047ed8d339479ccad51b88663David Blaikie if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) { 1196681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // FIXME: Assuming that BugReporter is a GRBugReporter is a layering 1197681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // violation. 1198681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags = 1199681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek cast<GRBugReporter>(BRC.getBugReporter()). 12000caa2d47b84337e942b3f6652adfafe4ae506cfeTed Kremenek getEngine().geteagerlyAssumeBinOpBifurcationTags(); 1201681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1202681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek const ProgramPointTag *tag = PS->getTag(); 1203681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (tag == tags.first) 1204220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return VisitTrueTest(cast<Expr>(PS->getStmt()), true, 120576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BRC, BR, N); 1206681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (tag == tags.second) 1207220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks return VisitTrueTest(cast<Expr>(PS->getStmt()), false, 120876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BRC, BR, N); 12096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1211993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek } 12126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 12136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1214993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek} 1215993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1216993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted KremenekPathDiagnosticPiece * 121750bbc165b063155cc23c360deb7b865502e068e2Anna ZaksConditionBRVisitor::VisitTerminator(const Stmt *Term, 1218220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks const ExplodedNode *N, 121950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const CFGBlock *srcBlk, 122050bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const CFGBlock *dstBlk, 122176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &R, 122250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks BugReporterContext &BRC) { 12236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Expr *Cond = nullptr; 12246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1225993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek switch (Term->getStmtClass()) { 1226993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek default: 12276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1228993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek case Stmt::IfStmtClass: 1229993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek Cond = cast<IfStmt>(Term)->getCond(); 1230993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek break; 1231993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek case Stmt::ConditionalOperatorClass: 1232993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek Cond = cast<ConditionalOperator>(Term)->getCond(); 1233993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek break; 1234993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek } 1235993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1236993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek assert(Cond); 1237993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek assert(srcBlk->succ_size() == 2); 1238993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek const bool tookTrue = *(srcBlk->succ_begin()) == dstBlk; 1239c47dc1b9734ea9bebb281499d58d22c2647713a9Ted Kremenek return VisitTrueTest(Cond, tookTrue, BRC, R, N); 1240993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek} 1241993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1242993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted KremenekPathDiagnosticPiece * 124350bbc165b063155cc23c360deb7b865502e068e2Anna ZaksConditionBRVisitor::VisitTrueTest(const Expr *Cond, 124450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks bool tookTrue, 1245220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks BugReporterContext &BRC, 124676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &R, 124776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const ExplodedNode *N) { 1248993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1249993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek const Expr *Ex = Cond; 1250993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1251681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek while (true) { 1252c47dc1b9734ea9bebb281499d58d22c2647713a9Ted Kremenek Ex = Ex->IgnoreParenCasts(); 1253993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek switch (Ex->getStmtClass()) { 1254993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek default: 12556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1256681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case Stmt::BinaryOperatorClass: 125776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC, 125876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R, N); 1259993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek case Stmt::DeclRefExprClass: 126076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC, 126176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek R, N); 1262993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek case Stmt::UnaryOperatorClass: { 1263993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek const UnaryOperator *UO = cast<UnaryOperator>(Ex); 1264993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek if (UO->getOpcode() == UO_LNot) { 1265993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek tookTrue = !tookTrue; 1266c47dc1b9734ea9bebb281499d58d22c2647713a9Ted Kremenek Ex = UO->getSubExpr(); 1267993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek continue; 1268993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek } 12696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1270993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek } 1271993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek } 1272681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1273681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek} 1274681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1275cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkobool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out, 127676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReporterContext &BRC, 127776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &report, 127876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const ExplodedNode *N, 1279dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<bool> &prunable) { 1280681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek const Expr *OriginalExpr = Ex; 1281681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Ex = Ex->IgnoreParenCasts(); 1282681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1283681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { 12843b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek const bool quotes = isa<VarDecl>(DR->getDecl()); 128576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (quotes) { 12863b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek Out << '\''; 128776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const LocationContext *LCtx = N->getLocationContext(); 1288ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ProgramState *state = N->getState().get(); 128976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()), 129076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek LCtx).getAsRegion()) { 129176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (report.isInteresting(R)) 129276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek prunable = false; 129376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek else { 1294ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ProgramState *state = N->getState().get(); 129576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek SVal V = state->getSVal(R); 129676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (report.isInteresting(V)) 129776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek prunable = false; 129876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 129976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 130076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 13013b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek Out << DR->getDecl()->getDeclName().getAsString(); 13023b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek if (quotes) 13033b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek Out << '\''; 13043b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek return quotes; 1305681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1306681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1307681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { 1308681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek QualType OriginalTy = OriginalExpr->getType(); 1309681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (OriginalTy->isPointerType()) { 1310681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (IL->getValue() == 0) { 1311681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << "null"; 13123b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek return false; 1313681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1314681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1315681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek else if (OriginalTy->isObjCObjectPointerType()) { 1316681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (IL->getValue() == 0) { 1317681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << "nil"; 13183b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek return false; 1319681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1320681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1321681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1322681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << IL->getValue(); 13233b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek return false; 1324681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 13253b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek 13263b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek return false; 1327681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek} 1328681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1329681bc114b51c1198cdec9a165c7d3230abb8f427Ted KremenekPathDiagnosticPiece * 133050bbc165b063155cc23c360deb7b865502e068e2Anna ZaksConditionBRVisitor::VisitTrueTest(const Expr *Cond, 133150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const BinaryOperator *BExpr, 133250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const bool tookTrue, 1333220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks BugReporterContext &BRC, 133476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &R, 133576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const ExplodedNode *N) { 1336681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 13373b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek bool shouldInvert = false; 1338dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<bool> shouldPrune; 13393b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek 1340f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> LhsString, RhsString; 1341681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek { 134276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString); 134376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N, 134476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek shouldPrune); 134576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N, 134676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek shouldPrune); 13473b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek 13483b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek shouldInvert = !isVarLHS && isVarRHS; 1349681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1350681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1351d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek BinaryOperator::Opcode Op = BExpr->getOpcode(); 1352d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 1353d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek if (BinaryOperator::isAssignmentOp(Op)) { 1354d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek // For assignment operators, all that we care about is that the LHS 1355d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek // evaluates to "true" or "false". 1356d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek return VisitConditionVariable(LhsString, BExpr->getLHS(), tookTrue, 135776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BRC, R, N); 1358d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek } 1359d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 1360d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek // For non-assignment operations, we require that we can understand 1361d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek // both the LHS and RHS. 13628686d857c5461d56852154bafc05644890a0eee0Jordan Rose if (LhsString.empty() || RhsString.empty() || 13638686d857c5461d56852154bafc05644890a0eee0Jordan Rose !BinaryOperator::isComparisonOp(Op)) 13646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 13656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1366d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek // Should we invert the strings if the LHS is not a variable name? 1367f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> buf; 1368681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek llvm::raw_svector_ostream Out(buf); 13693b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek Out << "Assuming " << (shouldInvert ? RhsString : LhsString) << " is "; 1370681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 1371681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek // Do we need to invert the opcode? 13723b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek if (shouldInvert) 13733b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek switch (Op) { 13743b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek default: break; 13753b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek case BO_LT: Op = BO_GT; break; 13763b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek case BO_GT: Op = BO_LT; break; 13773b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek case BO_LE: Op = BO_GE; break; 13783b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek case BO_GE: Op = BO_LE; break; 13793b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek } 13803b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek 1381681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek if (!tookTrue) 1382681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek switch (Op) { 1383681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_EQ: Op = BO_NE; break; 1384681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_NE: Op = BO_EQ; break; 1385681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_LT: Op = BO_GE; break; 1386681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_GT: Op = BO_LE; break; 1387681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_LE: Op = BO_GT; break; 13884ee7c9cedc015bc161fa290aa558356b9bcf1bfaTed Kremenek case BO_GE: Op = BO_LT; break; 1389681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek default: 13906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1391681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1392681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 13936ae325737c2ef7ce60ac6650a96bd489ef6e7ebeTed Kremenek switch (Op) { 1394681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_EQ: 1395681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << "equal to "; 1396681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek break; 1397681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek case BO_NE: 1398681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << "not equal to "; 1399681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek break; 1400681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek default: 1401681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek Out << BinaryOperator::getOpcodeStr(Op) << ' '; 1402681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek break; 1403681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek } 1404681bc114b51c1198cdec9a165c7d3230abb8f427Ted Kremenek 14053b9e8e40dab1295de4f14d9cf8d24c22422a42d2Ted Kremenek Out << (shouldInvert ? LhsString : RhsString); 140676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const LocationContext *LCtx = N->getLocationContext(); 140776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 140876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticEventPiece *event = 140976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek new PathDiagnosticEventPiece(Loc, Out.str()); 141076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (shouldPrune.hasValue()) 141176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek event->setPrunable(shouldPrune.getValue()); 141276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return event; 1413d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek} 1414d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 1415d1247c5002ee511e6f6c3c26214221c391d437cdTed KremenekPathDiagnosticPiece * 1416d1247c5002ee511e6f6c3c26214221c391d437cdTed KremenekConditionBRVisitor::VisitConditionVariable(StringRef LhsString, 1417d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek const Expr *CondVarExpr, 1418d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek const bool tookTrue, 1419d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek BugReporterContext &BRC, 142076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &report, 142176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const ExplodedNode *N) { 1422b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose // FIXME: If there's already a constraint tracker for this variable, 1423b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose // we shouldn't emit anything here (c.f. the double note in 1424b0e1badc2a9b8275b48dfb15c6907a282b949b02Jordan Rose // test/Analysis/inlining/path-notes.c) 1425f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> buf; 1426d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek llvm::raw_svector_ostream Out(buf); 1427d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek Out << "Assuming " << LhsString << " is "; 1428d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 1429d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek QualType Ty = CondVarExpr->getType(); 1430d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 1431d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek if (Ty->isPointerType()) 1432d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek Out << (tookTrue ? "not null" : "null"); 1433d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek else if (Ty->isObjCObjectPointerType()) 1434d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek Out << (tookTrue ? "not nil" : "nil"); 1435d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek else if (Ty->isBooleanType()) 1436d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek Out << (tookTrue ? "true" : "false"); 1437a5796f87229b4aeebca71fa6ee1790ae7a5a0382Jordan Rose else if (Ty->isIntegralOrEnumerationType()) 1438d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek Out << (tookTrue ? "non-zero" : "zero"); 1439d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek else 14406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1441d1247c5002ee511e6f6c3c26214221c391d437cdTed Kremenek 144276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const LocationContext *LCtx = N->getLocationContext(); 144376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); 144476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticEventPiece *event = 144576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek new PathDiagnosticEventPiece(Loc, Out.str()); 144676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 144776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { 144876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 1449ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ProgramState *state = N->getState().get(); 145076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 145176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (report.isInteresting(R)) 145276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek event->setPrunable(false); 145376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 145476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 145576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 145676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 145776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return event; 1458993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek} 1459993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1460993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted KremenekPathDiagnosticPiece * 146150bbc165b063155cc23c360deb7b865502e068e2Anna ZaksConditionBRVisitor::VisitTrueTest(const Expr *Cond, 146250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const DeclRefExpr *DR, 146350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks const bool tookTrue, 1464220ac8c175cb1bf9b18d82eefe036995d7a2164dAnna Zaks BugReporterContext &BRC, 146576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek BugReport &report, 146676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const ExplodedNode *N) { 1467993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1468993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); 1469993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek if (!VD) 14706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 14716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1472f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> Buf; 1473993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek llvm::raw_svector_ostream Out(Buf); 1474993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 147517828ca5857d5d9cadfffd339f888de58182c8f1David Blaikie Out << "Assuming '" << VD->getDeclName() << "' is "; 1476993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1477993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek QualType VDTy = VD->getType(); 1478993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek 1479993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek if (VDTy->isPointerType()) 1480993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek Out << (tookTrue ? "non-null" : "null"); 1481993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek else if (VDTy->isObjCObjectPointerType()) 1482993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek Out << (tookTrue ? "non-nil" : "nil"); 1483993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek else if (VDTy->isScalarType()) 1484993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek Out << (tookTrue ? "not equal to 0" : "0"); 1485993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek else 14866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 14876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 148876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek const LocationContext *LCtx = N->getLocationContext(); 148976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx); 149076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek PathDiagnosticEventPiece *event = 149176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek new PathDiagnosticEventPiece(Loc, Out.str()); 149276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek 1493ef8225444452a1486bd721f3285301fe84643b00Stephen Hines const ProgramState *state = N->getState().get(); 149476aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { 149576aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (report.isInteresting(R)) 149676aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek event->setPrunable(false); 149776aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek else { 149876aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek SVal V = state->getSVal(R); 149976aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek if (report.isInteresting(V)) 150076aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek event->setPrunable(false); 150176aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 150276aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek } 150376aadc346c3a4c363238a1e1232f324c3355d9e0Ted Kremenek return event; 1504993124ecdd44ec1430a3b7f01b22f65bbaadb586Ted Kremenek} 15050cf3d471546251b12bdceff360f66c079c40526cTed Kremenek 1506a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 1507a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose// FIXME: Copied from ExprEngineCallAndReturn.cpp. 1508a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rosestatic bool isInStdNamespace(const Decl *D) { 1509a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext(); 1510a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); 1511a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose if (!ND) 1512a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose return false; 1513a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 1514a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose while (const NamespaceDecl *Parent = dyn_cast<NamespaceDecl>(ND->getParent())) 1515a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose ND = Parent; 1516a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 15176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ND->isStdNamespace(); 1518a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose} 1519a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 1520a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 152180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna ZaksPathDiagnosticPiece * 152286ff12c8a8a356ca284ca7687749216fbfd74519Anna ZaksLikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, 152386ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks const ExplodedNode *N, 152486ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks BugReport &BR) { 1525a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose // Here we suppress false positives coming from system headers. This list is 152686ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks // based on known issues. 1527a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose ExprEngine &Eng = BRC.getBugReporter().getEngine(); 1528a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose AnalyzerOptions &Options = Eng.getAnalysisManager().options; 15298b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks const Decl *D = N->getLocationContext()->getDecl(); 15308b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks 15318b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks if (isInStdNamespace(D)) { 15328b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // Skip reports within the 'std' namespace. Although these can sometimes be 15338b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // the user's fault, we currently don't report them very well, and 15348b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // Note that this will not help for any other data structure libraries, like 15358b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // TR1, Boost, or llvm/ADT. 15368b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks if (Options.shouldSuppressFromCXXStandardLibrary()) { 15376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines BR.markInvalid(getTag(), nullptr); 15386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 15398b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks 15408b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks } else { 15418b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // If the the complete 'std' suppression is not enabled, suppress reports 15428b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // from the 'std' namespace that are known to produce false positives. 15438b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks 15448b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // The analyzer issues a false use-after-free when std::list::pop_front 15458b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // or std::list::pop_back are called multiple times because we cannot 15468b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks // reason about the internal invariants of the datastructure. 1547e600d4be7d01661ab7601f9ef9c4d3236c377385Anna Zaks if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { 1548e600d4be7d01661ab7601f9ef9c4d3236c377385Anna Zaks const CXXRecordDecl *CD = MD->getParent(); 1549e600d4be7d01661ab7601f9ef9c4d3236c377385Anna Zaks if (CD->getName() == "list") { 15506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines BR.markInvalid(getTag(), nullptr); 15516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1552e600d4be7d01661ab7601f9ef9c4d3236c377385Anna Zaks } 15538b625a3f7764959d0a2ac3cd860ce1e168e0fc9bAnna Zaks } 1554fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose 1555bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks // The analyzer issues a false positive on 1556bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks // std::basic_string<uint8_t> v; v.push_back(1); 1557fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose // and 1558fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose // std::u16string s; s += u'a'; 1559bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks // because we cannot reason about the internal invariants of the 1560bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks // datastructure. 1561651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const LocationContext *LCtx = N->getLocationContext(); LCtx; 1562651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LCtx = LCtx->getParent()) { 1563fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); 1564fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose if (!MD) 1565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1566fda9dbf1f4d15baaedffdd4b4bb529e06172f73dJordan Rose 1567bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks const CXXRecordDecl *CD = MD->getParent(); 1568bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks if (CD->getName() == "basic_string") { 15696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines BR.markInvalid(getTag(), nullptr); 15706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1571bdc0bf3f84b8771572d8401c66903c56a2e1318eAnna Zaks } 1572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1573a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose } 1574a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose } 1575a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose 157686ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks // Skip reports within the sys/queue.h macros as we do not have the ability to 157786ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks // reason about data structure shapes. 157886ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks SourceManager &SM = BRC.getSourceManager(); 1579a12643622ad3b85972dfdd80fe9006a3e8d8fb80Jordan Rose FullSourceLoc Loc = BR.getLocation(SM).asLocation(); 158086ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks while (Loc.isMacroID()) { 1581265448963a856bebdd0ae5abf67210054f44c64bAnna Zaks Loc = Loc.getSpellingLoc(); 1582265448963a856bebdd0ae5abf67210054f44c64bAnna Zaks if (SM.getFilename(Loc).endswith("sys/queue.h")) { 15836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines BR.markInvalid(getTag(), nullptr); 15846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 158586ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks } 158686ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks } 158786ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 15886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 158986ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks} 159086ff12c8a8a356ca284ca7687749216fbfd74519Anna Zaks 159186ff12c8a8a356ca284ca7687749216fbfd74519Anna ZaksPathDiagnosticPiece * 159280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna ZaksUndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, 159380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const ExplodedNode *PrevN, 159480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BugReporterContext &BRC, 159580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BugReport &BR) { 159680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 159780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks ProgramStateRef State = N->getState(); 159880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks ProgramPoint ProgLoc = N->getLocation(); 159980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 160080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // We are only interested in visiting CallEnter nodes. 16017a95de68c093991047ed8d339479ccad51b88663David Blaikie Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>(); 160280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!CEnter) 16036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 160480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 160580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check if one of the arguments is the region the visitor is tracking. 160680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); 160780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); 160880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks unsigned Idx = 0; 1609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<ParmVarDecl*> parms = Call->parameters(); 1610651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end(); 1612651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I != E; ++I, ++Idx) { 161380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); 161480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 1615522fc21f3adc647817edc8017e6928a64c96899bAnna Zaks // Are we tracking the argument or its subregion? 1616522fc21f3adc647817edc8017e6928a64c96899bAnna Zaks if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) 161728694c1fe44082970cd53ca7ffef25f668e4c545Anna Zaks continue; 161880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 161980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Check the function parameter type. 162080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks const ParmVarDecl *ParamDecl = *I; 162180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks assert(ParamDecl && "Formal parameter has no decl?"); 162280de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks QualType T = ParamDecl->getType(); 162380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 162480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (!(T->isAnyPointerType() || T->isReferenceType())) { 162580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Function can only change the value passed in by address. 162628694c1fe44082970cd53ca7ffef25f668e4c545Anna Zaks continue; 162780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 162880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 162980de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // If it is a const pointer value, the function does not intend to 163080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // change the value. 163180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (T->getPointeeType().isConstQualified()) 163228694c1fe44082970cd53ca7ffef25f668e4c545Anna Zaks continue; 163380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks 163480de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // Mark the call site (LocationContext) as interesting if the value of the 163580de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks // argument is undefined or '0'/'NULL'. 1636522fc21f3adc647817edc8017e6928a64c96899bAnna Zaks SVal BoundVal = State->getSVal(R); 163780de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { 163880de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks BR.markInteresting(CEnter->getCalleeContext()); 16396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 164080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 164180de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks } 16426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 164380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks} 1644