1 //===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a set of BugReporter "visitors" which can be used to
10 // enhance the diagnostics reported for a bug.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/ExprObjC.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/Type.h"
24 #include "clang/ASTMatchers/ASTMatchFinder.h"
25 #include "clang/Analysis/Analyses/Dominators.h"
26 #include "clang/Analysis/AnalysisDeclContext.h"
27 #include "clang/Analysis/CFG.h"
28 #include "clang/Analysis/CFGStmtMap.h"
29 #include "clang/Analysis/PathDiagnostic.h"
30 #include "clang/Analysis/ProgramPoint.h"
31 #include "clang/Basic/IdentifierTable.h"
32 #include "clang/Basic/LLVM.h"
33 #include "clang/Basic/SourceLocation.h"
34 #include "clang/Basic/SourceManager.h"
35 #include "clang/Lex/Lexer.h"
36 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
37 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
38 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
39 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
40 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
41 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
42 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
43 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
44 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
45 #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
46 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
47 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
48 #include "llvm/ADT/ArrayRef.h"
49 #include "llvm/ADT/None.h"
50 #include "llvm/ADT/Optional.h"
51 #include "llvm/ADT/STLExtras.h"
52 #include "llvm/ADT/SmallPtrSet.h"
53 #include "llvm/ADT/SmallString.h"
54 #include "llvm/ADT/SmallVector.h"
55 #include "llvm/ADT/StringExtras.h"
56 #include "llvm/ADT/StringRef.h"
57 #include "llvm/Support/Casting.h"
58 #include "llvm/Support/ErrorHandling.h"
59 #include "llvm/Support/raw_ostream.h"
60 #include <cassert>
61 #include <deque>
62 #include <memory>
63 #include <string>
64 #include <utility>
65
66 using namespace clang;
67 using namespace ento;
68 using namespace bugreporter;
69
70 //===----------------------------------------------------------------------===//
71 // Utility functions.
72 //===----------------------------------------------------------------------===//
73
peelOffPointerArithmetic(const BinaryOperator * B)74 static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
75 if (B->isAdditiveOp() && B->getType()->isPointerType()) {
76 if (B->getLHS()->getType()->isPointerType()) {
77 return B->getLHS();
78 } else if (B->getRHS()->getType()->isPointerType()) {
79 return B->getRHS();
80 }
81 }
82 return nullptr;
83 }
84
85 /// Given that expression S represents a pointer that would be dereferenced,
86 /// try to find a sub-expression from which the pointer came from.
87 /// This is used for tracking down origins of a null or undefined value:
88 /// "this is null because that is null because that is null" etc.
89 /// We wipe away field and element offsets because they merely add offsets.
90 /// We also wipe away all casts except lvalue-to-rvalue casts, because the
91 /// latter represent an actual pointer dereference; however, we remove
92 /// the final lvalue-to-rvalue cast before returning from this function
93 /// because it demonstrates more clearly from where the pointer rvalue was
94 /// loaded. Examples:
95 /// x->y.z ==> x (lvalue)
96 /// foo()->y.z ==> foo() (rvalue)
getDerefExpr(const Stmt * S)97 const Expr *bugreporter::getDerefExpr(const Stmt *S) {
98 const auto *E = dyn_cast<Expr>(S);
99 if (!E)
100 return nullptr;
101
102 while (true) {
103 if (const auto *CE = dyn_cast<CastExpr>(E)) {
104 if (CE->getCastKind() == CK_LValueToRValue) {
105 // This cast represents the load we're looking for.
106 break;
107 }
108 E = CE->getSubExpr();
109 } else if (const auto *B = dyn_cast<BinaryOperator>(E)) {
110 // Pointer arithmetic: '*(x + 2)' -> 'x') etc.
111 if (const Expr *Inner = peelOffPointerArithmetic(B)) {
112 E = Inner;
113 } else {
114 // Probably more arithmetic can be pattern-matched here,
115 // but for now give up.
116 break;
117 }
118 } else if (const auto *U = dyn_cast<UnaryOperator>(E)) {
119 if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
120 (U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
121 // Operators '*' and '&' don't actually mean anything.
122 // We look at casts instead.
123 E = U->getSubExpr();
124 } else {
125 // Probably more arithmetic can be pattern-matched here,
126 // but for now give up.
127 break;
128 }
129 }
130 // Pattern match for a few useful cases: a[0], p->f, *p etc.
131 else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
132 E = ME->getBase();
133 } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
134 E = IvarRef->getBase();
135 } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
136 E = AE->getBase();
137 } else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
138 E = PE->getSubExpr();
139 } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
140 E = FE->getSubExpr();
141 } else {
142 // Other arbitrary stuff.
143 break;
144 }
145 }
146
147 // Special case: remove the final lvalue-to-rvalue cast, but do not recurse
148 // deeper into the sub-expression. This way we return the lvalue from which
149 // our pointer rvalue was loaded.
150 if (const auto *CE = dyn_cast<ImplicitCastExpr>(E))
151 if (CE->getCastKind() == CK_LValueToRValue)
152 E = CE->getSubExpr();
153
154 return E;
155 }
156
157 static const MemRegion *
getLocationRegionIfReference(const Expr * E,const ExplodedNode * N,bool LookingForReference=true)158 getLocationRegionIfReference(const Expr *E, const ExplodedNode *N,
159 bool LookingForReference = true) {
160 if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
161 if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
162 if (LookingForReference && !VD->getType()->isReferenceType())
163 return nullptr;
164 return N->getState()
165 ->getLValue(VD, N->getLocationContext())
166 .getAsRegion();
167 }
168 }
169
170 // FIXME: This does not handle other kinds of null references,
171 // for example, references from FieldRegions:
172 // struct Wrapper { int &ref; };
173 // Wrapper w = { *(int *)0 };
174 // w.ref = 1;
175
176 return nullptr;
177 }
178
179 /// Comparing internal representations of symbolic values (via
180 /// SVal::operator==()) is a valid way to check if the value was updated,
181 /// unless it's a LazyCompoundVal that may have a different internal
182 /// representation every time it is loaded from the state. In this function we
183 /// do an approximate comparison for lazy compound values, checking that they
184 /// are the immediate snapshots of the tracked region's bindings within the
185 /// node's respective states but not really checking that these snapshots
186 /// actually contain the same set of bindings.
hasVisibleUpdate(const ExplodedNode * LeftNode,SVal LeftVal,const ExplodedNode * RightNode,SVal RightVal)187 static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
188 const ExplodedNode *RightNode, SVal RightVal) {
189 if (LeftVal == RightVal)
190 return true;
191
192 const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
193 if (!LLCV)
194 return false;
195
196 const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
197 if (!RLCV)
198 return false;
199
200 return LLCV->getRegion() == RLCV->getRegion() &&
201 LLCV->getStore() == LeftNode->getState()->getStore() &&
202 RLCV->getStore() == RightNode->getState()->getStore();
203 }
204
getSValForVar(const Expr * CondVarExpr,const ExplodedNode * N)205 static Optional<SVal> getSValForVar(const Expr *CondVarExpr,
206 const ExplodedNode *N) {
207 ProgramStateRef State = N->getState();
208 const LocationContext *LCtx = N->getLocationContext();
209
210 assert(CondVarExpr);
211 CondVarExpr = CondVarExpr->IgnoreImpCasts();
212
213 // The declaration of the value may rely on a pointer so take its l-value.
214 // FIXME: As seen in VisitCommonDeclRefExpr, sometimes DeclRefExpr may
215 // evaluate to a FieldRegion when it refers to a declaration of a lambda
216 // capture variable. We most likely need to duplicate that logic here.
217 if (const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr))
218 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
219 return State->getSVal(State->getLValue(VD, LCtx));
220
221 if (const auto *ME = dyn_cast<MemberExpr>(CondVarExpr))
222 if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
223 if (auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>())
224 return State->getRawSVal(*FieldL, FD->getType());
225
226 return None;
227 }
228
229 static Optional<const llvm::APSInt *>
getConcreteIntegerValue(const Expr * CondVarExpr,const ExplodedNode * N)230 getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) {
231
232 if (Optional<SVal> V = getSValForVar(CondVarExpr, N))
233 if (auto CI = V->getAs<nonloc::ConcreteInt>())
234 return &CI->getValue();
235 return None;
236 }
237
isVarAnInterestingCondition(const Expr * CondVarExpr,const ExplodedNode * N,const PathSensitiveBugReport * B)238 static bool isVarAnInterestingCondition(const Expr *CondVarExpr,
239 const ExplodedNode *N,
240 const PathSensitiveBugReport *B) {
241 // Even if this condition is marked as interesting, it isn't *that*
242 // interesting if it didn't happen in a nested stackframe, the user could just
243 // follow the arrows.
244 if (!B->getErrorNode()->getStackFrame()->isParentOf(N->getStackFrame()))
245 return false;
246
247 if (Optional<SVal> V = getSValForVar(CondVarExpr, N))
248 if (Optional<bugreporter::TrackingKind> K = B->getInterestingnessKind(*V))
249 return *K == bugreporter::TrackingKind::Condition;
250
251 return false;
252 }
253
isInterestingExpr(const Expr * E,const ExplodedNode * N,const PathSensitiveBugReport * B)254 static bool isInterestingExpr(const Expr *E, const ExplodedNode *N,
255 const PathSensitiveBugReport *B) {
256 if (Optional<SVal> V = getSValForVar(E, N))
257 return B->getInterestingnessKind(*V).hasValue();
258 return false;
259 }
260
261 /// \return name of the macro inside the location \p Loc.
getMacroName(SourceLocation Loc,BugReporterContext & BRC)262 static StringRef getMacroName(SourceLocation Loc,
263 BugReporterContext &BRC) {
264 return Lexer::getImmediateMacroName(
265 Loc,
266 BRC.getSourceManager(),
267 BRC.getASTContext().getLangOpts());
268 }
269
270 /// \return Whether given spelling location corresponds to an expansion
271 /// of a function-like macro.
isFunctionMacroExpansion(SourceLocation Loc,const SourceManager & SM)272 static bool isFunctionMacroExpansion(SourceLocation Loc,
273 const SourceManager &SM) {
274 if (!Loc.isMacroID())
275 return false;
276 while (SM.isMacroArgExpansion(Loc))
277 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
278 std::pair<FileID, unsigned> TLInfo = SM.getDecomposedLoc(Loc);
279 SrcMgr::SLocEntry SE = SM.getSLocEntry(TLInfo.first);
280 const SrcMgr::ExpansionInfo &EInfo = SE.getExpansion();
281 return EInfo.isFunctionMacroExpansion();
282 }
283
284 /// \return Whether \c RegionOfInterest was modified at \p N,
285 /// where \p ValueAfter is \c RegionOfInterest's value at the end of the
286 /// stack frame.
wasRegionOfInterestModifiedAt(const SubRegion * RegionOfInterest,const ExplodedNode * N,SVal ValueAfter)287 static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest,
288 const ExplodedNode *N,
289 SVal ValueAfter) {
290 ProgramStateRef State = N->getState();
291 ProgramStateManager &Mgr = N->getState()->getStateManager();
292
293 if (!N->getLocationAs<PostStore>() && !N->getLocationAs<PostInitializer>() &&
294 !N->getLocationAs<PostStmt>())
295 return false;
296
297 // Writing into region of interest.
298 if (auto PS = N->getLocationAs<PostStmt>())
299 if (auto *BO = PS->getStmtAs<BinaryOperator>())
300 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
301 N->getSVal(BO->getLHS()).getAsRegion()))
302 return true;
303
304 // SVal after the state is possibly different.
305 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
306 if (!Mgr.getSValBuilder()
307 .areEqual(State, ValueAtN, ValueAfter)
308 .isConstrainedTrue() &&
309 (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
310 return true;
311
312 return false;
313 }
314
315 //===----------------------------------------------------------------------===//
316 // Implementation of BugReporterVisitor.
317 //===----------------------------------------------------------------------===//
318
getEndPath(BugReporterContext &,const ExplodedNode *,PathSensitiveBugReport &)319 PathDiagnosticPieceRef BugReporterVisitor::getEndPath(BugReporterContext &,
320 const ExplodedNode *,
321 PathSensitiveBugReport &) {
322 return nullptr;
323 }
324
finalizeVisitor(BugReporterContext &,const ExplodedNode *,PathSensitiveBugReport &)325 void BugReporterVisitor::finalizeVisitor(BugReporterContext &,
326 const ExplodedNode *,
327 PathSensitiveBugReport &) {}
328
329 PathDiagnosticPieceRef
getDefaultEndPath(const BugReporterContext & BRC,const ExplodedNode * EndPathNode,const PathSensitiveBugReport & BR)330 BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC,
331 const ExplodedNode *EndPathNode,
332 const PathSensitiveBugReport &BR) {
333 PathDiagnosticLocation L = BR.getLocation();
334 const auto &Ranges = BR.getRanges();
335
336 // Only add the statement itself as a range if we didn't specify any
337 // special ranges for this report.
338 auto P = std::make_shared<PathDiagnosticEventPiece>(
339 L, BR.getDescription(), Ranges.begin() == Ranges.end());
340 for (SourceRange Range : Ranges)
341 P->addRange(Range);
342
343 return P;
344 }
345
346 //===----------------------------------------------------------------------===//
347 // Implementation of NoStoreFuncVisitor.
348 //===----------------------------------------------------------------------===//
349
350 namespace {
351
352 /// Put a diagnostic on return statement of all inlined functions
353 /// for which the region of interest \p RegionOfInterest was passed into,
354 /// but not written inside, and it has caused an undefined read or a null
355 /// pointer dereference outside.
356 class NoStoreFuncVisitor final : public BugReporterVisitor {
357 const SubRegion *RegionOfInterest;
358 MemRegionManager &MmrMgr;
359 const SourceManager &SM;
360 const PrintingPolicy &PP;
361 bugreporter::TrackingKind TKind;
362
363 /// Recursion limit for dereferencing fields when looking for the
364 /// region of interest.
365 /// The limit of two indicates that we will dereference fields only once.
366 static const unsigned DEREFERENCE_LIMIT = 2;
367
368 /// Frames writing into \c RegionOfInterest.
369 /// This visitor generates a note only if a function does not write into
370 /// a region of interest. This information is not immediately available
371 /// by looking at the node associated with the exit from the function
372 /// (usually the return statement). To avoid recomputing the same information
373 /// many times (going up the path for each node and checking whether the
374 /// region was written into) we instead lazily compute the
375 /// stack frames along the path which write into the region of interest.
376 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
377 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
378
379 using RegionVector = SmallVector<const MemRegion *, 5>;
380
381 public:
NoStoreFuncVisitor(const SubRegion * R,bugreporter::TrackingKind TKind)382 NoStoreFuncVisitor(const SubRegion *R, bugreporter::TrackingKind TKind)
383 : RegionOfInterest(R), MmrMgr(R->getMemRegionManager()),
384 SM(MmrMgr.getContext().getSourceManager()),
385 PP(MmrMgr.getContext().getPrintingPolicy()), TKind(TKind) {}
386
Profile(llvm::FoldingSetNodeID & ID) const387 void Profile(llvm::FoldingSetNodeID &ID) const override {
388 static int Tag = 0;
389 ID.AddPointer(&Tag);
390 ID.AddPointer(RegionOfInterest);
391 }
392
getTag() const393 void *getTag() const {
394 static int Tag = 0;
395 return static_cast<void *>(&Tag);
396 }
397
398 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
399 BugReporterContext &BR,
400 PathSensitiveBugReport &R) override;
401
402 private:
403 /// Attempts to find the region of interest in a given record decl,
404 /// by either following the base classes or fields.
405 /// Dereferences fields up to a given recursion limit.
406 /// Note that \p Vec is passed by value, leading to quadratic copying cost,
407 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
408 /// \return A chain fields leading to the region of interest or None.
409 const Optional<RegionVector>
410 findRegionOfInterestInRecord(const RecordDecl *RD, ProgramStateRef State,
411 const MemRegion *R, const RegionVector &Vec = {},
412 int depth = 0);
413
414 /// Check and lazily calculate whether the region of interest is
415 /// modified in the stack frame to which \p N belongs.
416 /// The calculation is cached in FramesModifyingRegion.
isRegionOfInterestModifiedInFrame(const ExplodedNode * N)417 bool isRegionOfInterestModifiedInFrame(const ExplodedNode *N) {
418 const LocationContext *Ctx = N->getLocationContext();
419 const StackFrameContext *SCtx = Ctx->getStackFrame();
420 if (!FramesModifyingCalculated.count(SCtx))
421 findModifyingFrames(N);
422 return FramesModifyingRegion.count(SCtx);
423 }
424
425 /// Write to \c FramesModifyingRegion all stack frames along
426 /// the path in the current stack frame which modify \c RegionOfInterest.
427 void findModifyingFrames(const ExplodedNode *N);
428
429 /// Consume the information on the no-store stack frame in order to
430 /// either emit a note or suppress the report enirely.
431 /// \return Diagnostics piece for region not modified in the current function,
432 /// if it decides to emit one.
433 PathDiagnosticPieceRef
434 maybeEmitNote(PathSensitiveBugReport &R, const CallEvent &Call,
435 const ExplodedNode *N, const RegionVector &FieldChain,
436 const MemRegion *MatchedRegion, StringRef FirstElement,
437 bool FirstIsReferenceType, unsigned IndirectionLevel);
438
439 /// Pretty-print region \p MatchedRegion to \p os.
440 /// \return Whether printing succeeded.
441 bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType,
442 const MemRegion *MatchedRegion,
443 const RegionVector &FieldChain,
444 int IndirectionLevel,
445 llvm::raw_svector_ostream &os);
446
447 /// Print first item in the chain, return new separator.
448 static StringRef prettyPrintFirstElement(StringRef FirstElement,
449 bool MoreItemsExpected,
450 int IndirectionLevel,
451 llvm::raw_svector_ostream &os);
452 };
453
454 } // end of anonymous namespace
455
456 /// \return Whether the method declaration \p Parent
457 /// syntactically has a binary operation writing into the ivar \p Ivar.
potentiallyWritesIntoIvar(const Decl * Parent,const ObjCIvarDecl * Ivar)458 static bool potentiallyWritesIntoIvar(const Decl *Parent,
459 const ObjCIvarDecl *Ivar) {
460 using namespace ast_matchers;
461 const char *IvarBind = "Ivar";
462 if (!Parent || !Parent->hasBody())
463 return false;
464 StatementMatcher WriteIntoIvarM = binaryOperator(
465 hasOperatorName("="),
466 hasLHS(ignoringParenImpCasts(
467 objcIvarRefExpr(hasDeclaration(equalsNode(Ivar))).bind(IvarBind))));
468 StatementMatcher ParentM = stmt(hasDescendant(WriteIntoIvarM));
469 auto Matches = match(ParentM, *Parent->getBody(), Parent->getASTContext());
470 for (BoundNodes &Match : Matches) {
471 auto IvarRef = Match.getNodeAs<ObjCIvarRefExpr>(IvarBind);
472 if (IvarRef->isFreeIvar())
473 return true;
474
475 const Expr *Base = IvarRef->getBase();
476 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
477 Base = ICE->getSubExpr();
478
479 if (const auto *DRE = dyn_cast<DeclRefExpr>(Base))
480 if (const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
481 if (ID->getParameterKind() == ImplicitParamDecl::ObjCSelf)
482 return true;
483
484 return false;
485 }
486 return false;
487 }
488
489 /// Get parameters associated with runtime definition in order
490 /// to get the correct parameter name.
getCallParameters(CallEventRef<> Call)491 static ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) {
492 // Use runtime definition, if available.
493 RuntimeDefinition RD = Call->getRuntimeDefinition();
494 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
495 return FD->parameters();
496 if (const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
497 return MD->parameters();
498
499 return Call->parameters();
500 }
501
502 /// \return whether \p Ty points to a const type, or is a const reference.
isPointerToConst(QualType Ty)503 static bool isPointerToConst(QualType Ty) {
504 return !Ty->getPointeeType().isNull() &&
505 Ty->getPointeeType().getCanonicalType().isConstQualified();
506 }
507
508 /// Attempts to find the region of interest in a given CXX decl,
509 /// by either following the base classes or fields.
510 /// Dereferences fields up to a given recursion limit.
511 /// Note that \p Vec is passed by value, leading to quadratic copying cost,
512 /// but it's OK in practice since its length is limited to DEREFERENCE_LIMIT.
513 /// \return A chain fields leading to the region of interest or None.
514 const Optional<NoStoreFuncVisitor::RegionVector>
findRegionOfInterestInRecord(const RecordDecl * RD,ProgramStateRef State,const MemRegion * R,const NoStoreFuncVisitor::RegionVector & Vec,int depth)515 NoStoreFuncVisitor::findRegionOfInterestInRecord(
516 const RecordDecl *RD, ProgramStateRef State, const MemRegion *R,
517 const NoStoreFuncVisitor::RegionVector &Vec /* = {} */,
518 int depth /* = 0 */) {
519
520 if (depth == DEREFERENCE_LIMIT) // Limit the recursion depth.
521 return None;
522
523 if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
524 if (!RDX->hasDefinition())
525 return None;
526
527 // Recursively examine the base classes.
528 // Note that following base classes does not increase the recursion depth.
529 if (const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
530 for (const auto &II : RDX->bases())
531 if (const RecordDecl *RRD = II.getType()->getAsRecordDecl())
532 if (Optional<RegionVector> Out =
533 findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
534 return Out;
535
536 for (const FieldDecl *I : RD->fields()) {
537 QualType FT = I->getType();
538 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
539 const SVal V = State->getSVal(FR);
540 const MemRegion *VR = V.getAsRegion();
541
542 RegionVector VecF = Vec;
543 VecF.push_back(FR);
544
545 if (RegionOfInterest == VR)
546 return VecF;
547
548 if (const RecordDecl *RRD = FT->getAsRecordDecl())
549 if (auto Out =
550 findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
551 return Out;
552
553 QualType PT = FT->getPointeeType();
554 if (PT.isNull() || PT->isVoidType() || !VR)
555 continue;
556
557 if (const RecordDecl *RRD = PT->getAsRecordDecl())
558 if (Optional<RegionVector> Out =
559 findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
560 return Out;
561 }
562
563 return None;
564 }
565
566 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BR,PathSensitiveBugReport & R)567 NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BR,
568 PathSensitiveBugReport &R) {
569
570 const LocationContext *Ctx = N->getLocationContext();
571 const StackFrameContext *SCtx = Ctx->getStackFrame();
572 ProgramStateRef State = N->getState();
573 auto CallExitLoc = N->getLocationAs<CallExitBegin>();
574
575 // No diagnostic if region was modified inside the frame.
576 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
577 return nullptr;
578
579 CallEventRef<> Call =
580 BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
581
582 // Region of interest corresponds to an IVar, exiting a method
583 // which could have written into that IVar, but did not.
584 if (const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
585 if (const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
586 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
587 if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
588 potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
589 IvarR->getDecl()))
590 return maybeEmitNote(R, *Call, N, {}, SelfRegion, "self",
591 /*FirstIsReferenceType=*/false, 1);
592 }
593 }
594
595 if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
596 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
597 if (RegionOfInterest->isSubRegionOf(ThisR) &&
598 !CCall->getDecl()->isImplicit())
599 return maybeEmitNote(R, *Call, N, {}, ThisR, "this",
600 /*FirstIsReferenceType=*/false, 1);
601
602 // Do not generate diagnostics for not modified parameters in
603 // constructors.
604 return nullptr;
605 }
606
607 ArrayRef<ParmVarDecl *> parameters = getCallParameters(Call);
608 for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
609 const ParmVarDecl *PVD = parameters[I];
610 SVal V = Call->getArgSVal(I);
611 bool ParamIsReferenceType = PVD->getType()->isReferenceType();
612 std::string ParamName = PVD->getNameAsString();
613
614 int IndirectionLevel = 1;
615 QualType T = PVD->getType();
616 while (const MemRegion *MR = V.getAsRegion()) {
617 if (RegionOfInterest->isSubRegionOf(MR) && !isPointerToConst(T))
618 return maybeEmitNote(R, *Call, N, {}, MR, ParamName,
619 ParamIsReferenceType, IndirectionLevel);
620
621 QualType PT = T->getPointeeType();
622 if (PT.isNull() || PT->isVoidType())
623 break;
624
625 if (const RecordDecl *RD = PT->getAsRecordDecl())
626 if (Optional<RegionVector> P =
627 findRegionOfInterestInRecord(RD, State, MR))
628 return maybeEmitNote(R, *Call, N, *P, RegionOfInterest, ParamName,
629 ParamIsReferenceType, IndirectionLevel);
630
631 V = State->getSVal(MR, PT);
632 T = PT;
633 IndirectionLevel++;
634 }
635 }
636
637 return nullptr;
638 }
639
findModifyingFrames(const ExplodedNode * N)640 void NoStoreFuncVisitor::findModifyingFrames(const ExplodedNode *N) {
641 assert(N->getLocationAs<CallExitBegin>());
642 ProgramStateRef LastReturnState = N->getState();
643 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
644 const LocationContext *Ctx = N->getLocationContext();
645 const StackFrameContext *OriginalSCtx = Ctx->getStackFrame();
646
647 do {
648 ProgramStateRef State = N->getState();
649 auto CallExitLoc = N->getLocationAs<CallExitBegin>();
650 if (CallExitLoc) {
651 LastReturnState = State;
652 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
653 }
654
655 FramesModifyingCalculated.insert(N->getLocationContext()->getStackFrame());
656
657 if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) {
658 const StackFrameContext *SCtx = N->getStackFrame();
659 while (!SCtx->inTopFrame()) {
660 auto p = FramesModifyingRegion.insert(SCtx);
661 if (!p.second)
662 break; // Frame and all its parents already inserted.
663 SCtx = SCtx->getParent()->getStackFrame();
664 }
665 }
666
667 // Stop calculation at the call to the current function.
668 if (auto CE = N->getLocationAs<CallEnter>())
669 if (CE->getCalleeContext() == OriginalSCtx)
670 break;
671
672 N = N->getFirstPred();
673 } while (N);
674 }
675
676 static llvm::StringLiteral WillBeUsedForACondition =
677 ", which participates in a condition later";
678
maybeEmitNote(PathSensitiveBugReport & R,const CallEvent & Call,const ExplodedNode * N,const RegionVector & FieldChain,const MemRegion * MatchedRegion,StringRef FirstElement,bool FirstIsReferenceType,unsigned IndirectionLevel)679 PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote(
680 PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N,
681 const RegionVector &FieldChain, const MemRegion *MatchedRegion,
682 StringRef FirstElement, bool FirstIsReferenceType,
683 unsigned IndirectionLevel) {
684 // Optimistically suppress uninitialized value bugs that result
685 // from system headers having a chance to initialize the value
686 // but failing to do so. It's too unlikely a system header's fault.
687 // It's much more likely a situation in which the function has a failure
688 // mode that the user decided not to check. If we want to hunt such
689 // omitted checks, we should provide an explicit function-specific note
690 // describing the precondition under which the function isn't supposed to
691 // initialize its out-parameter, and additionally check that such
692 // precondition can actually be fulfilled on the current path.
693 if (Call.isInSystemHeader()) {
694 // We make an exception for system header functions that have no branches.
695 // Such functions unconditionally fail to initialize the variable.
696 // If they call other functions that have more paths within them,
697 // this suppression would still apply when we visit these inner functions.
698 // One common example of a standard function that doesn't ever initialize
699 // its out parameter is operator placement new; it's up to the follow-up
700 // constructor (if any) to initialize the memory.
701 if (!N->getStackFrame()->getCFG()->isLinear())
702 R.markInvalid(getTag(), nullptr);
703 return nullptr;
704 }
705
706 PathDiagnosticLocation L =
707 PathDiagnosticLocation::create(N->getLocation(), SM);
708
709 // For now this shouldn't trigger, but once it does (as we add more
710 // functions to the body farm), we'll need to decide if these reports
711 // are worth suppressing as well.
712 if (!L.hasValidLocation())
713 return nullptr;
714
715 SmallString<256> sbuf;
716 llvm::raw_svector_ostream os(sbuf);
717 os << "Returning without writing to '";
718
719 // Do not generate the note if failed to pretty-print.
720 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion,
721 FieldChain, IndirectionLevel, os))
722 return nullptr;
723
724 os << "'";
725 if (TKind == bugreporter::TrackingKind::Condition)
726 os << WillBeUsedForACondition;
727 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
728 }
729
prettyPrintRegionName(StringRef FirstElement,bool FirstIsReferenceType,const MemRegion * MatchedRegion,const RegionVector & FieldChain,int IndirectionLevel,llvm::raw_svector_ostream & os)730 bool NoStoreFuncVisitor::prettyPrintRegionName(StringRef FirstElement,
731 bool FirstIsReferenceType,
732 const MemRegion *MatchedRegion,
733 const RegionVector &FieldChain,
734 int IndirectionLevel,
735 llvm::raw_svector_ostream &os) {
736
737 if (FirstIsReferenceType)
738 IndirectionLevel--;
739
740 RegionVector RegionSequence;
741
742 // Add the regions in the reverse order, then reverse the resulting array.
743 assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
744 const MemRegion *R = RegionOfInterest;
745 while (R != MatchedRegion) {
746 RegionSequence.push_back(R);
747 R = cast<SubRegion>(R)->getSuperRegion();
748 }
749 std::reverse(RegionSequence.begin(), RegionSequence.end());
750 RegionSequence.append(FieldChain.begin(), FieldChain.end());
751
752 StringRef Sep;
753 for (const MemRegion *R : RegionSequence) {
754
755 // Just keep going up to the base region.
756 // Element regions may appear due to casts.
757 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
758 continue;
759
760 if (Sep.empty())
761 Sep = prettyPrintFirstElement(FirstElement,
762 /*MoreItemsExpected=*/true,
763 IndirectionLevel, os);
764
765 os << Sep;
766
767 // Can only reasonably pretty-print DeclRegions.
768 if (!isa<DeclRegion>(R))
769 return false;
770
771 const auto *DR = cast<DeclRegion>(R);
772 Sep = DR->getValueType()->isAnyPointerType() ? "->" : ".";
773 DR->getDecl()->getDeclName().print(os, PP);
774 }
775
776 if (Sep.empty())
777 prettyPrintFirstElement(FirstElement,
778 /*MoreItemsExpected=*/false, IndirectionLevel, os);
779 return true;
780 }
781
prettyPrintFirstElement(StringRef FirstElement,bool MoreItemsExpected,int IndirectionLevel,llvm::raw_svector_ostream & os)782 StringRef NoStoreFuncVisitor::prettyPrintFirstElement(
783 StringRef FirstElement, bool MoreItemsExpected, int IndirectionLevel,
784 llvm::raw_svector_ostream &os) {
785 StringRef Out = ".";
786
787 if (IndirectionLevel > 0 && MoreItemsExpected) {
788 IndirectionLevel--;
789 Out = "->";
790 }
791
792 if (IndirectionLevel > 0 && MoreItemsExpected)
793 os << "(";
794
795 for (int i = 0; i < IndirectionLevel; i++)
796 os << "*";
797 os << FirstElement;
798
799 if (IndirectionLevel > 0 && MoreItemsExpected)
800 os << ")";
801
802 return Out;
803 }
804
805 //===----------------------------------------------------------------------===//
806 // Implementation of MacroNullReturnSuppressionVisitor.
807 //===----------------------------------------------------------------------===//
808
809 namespace {
810
811 /// Suppress null-pointer-dereference bugs where dereferenced null was returned
812 /// the macro.
813 class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor {
814 const SubRegion *RegionOfInterest;
815 const SVal ValueAtDereference;
816
817 // Do not invalidate the reports where the value was modified
818 // after it got assigned to from the macro.
819 bool WasModified = false;
820
821 public:
MacroNullReturnSuppressionVisitor(const SubRegion * R,const SVal V)822 MacroNullReturnSuppressionVisitor(const SubRegion *R, const SVal V)
823 : RegionOfInterest(R), ValueAtDereference(V) {}
824
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)825 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
826 BugReporterContext &BRC,
827 PathSensitiveBugReport &BR) override {
828 if (WasModified)
829 return nullptr;
830
831 auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
832 if (!BugPoint)
833 return nullptr;
834
835 const SourceManager &SMgr = BRC.getSourceManager();
836 if (auto Loc = matchAssignment(N)) {
837 if (isFunctionMacroExpansion(*Loc, SMgr)) {
838 std::string MacroName = std::string(getMacroName(*Loc, BRC));
839 SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
840 if (!BugLoc.isMacroID() || getMacroName(BugLoc, BRC) != MacroName)
841 BR.markInvalid(getTag(), MacroName.c_str());
842 }
843 }
844
845 if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference))
846 WasModified = true;
847
848 return nullptr;
849 }
850
addMacroVisitorIfNecessary(const ExplodedNode * N,const MemRegion * R,bool EnableNullFPSuppression,PathSensitiveBugReport & BR,const SVal V)851 static void addMacroVisitorIfNecessary(
852 const ExplodedNode *N, const MemRegion *R,
853 bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
854 const SVal V) {
855 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
856 if (EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths &&
857 V.getAs<Loc>())
858 BR.addVisitor<MacroNullReturnSuppressionVisitor>(R->getAs<SubRegion>(),
859 V);
860 }
861
getTag() const862 void* getTag() const {
863 static int Tag = 0;
864 return static_cast<void *>(&Tag);
865 }
866
Profile(llvm::FoldingSetNodeID & ID) const867 void Profile(llvm::FoldingSetNodeID &ID) const override {
868 ID.AddPointer(getTag());
869 }
870
871 private:
872 /// \return Source location of right hand side of an assignment
873 /// into \c RegionOfInterest, empty optional if none found.
matchAssignment(const ExplodedNode * N)874 Optional<SourceLocation> matchAssignment(const ExplodedNode *N) {
875 const Stmt *S = N->getStmtForDiagnostics();
876 ProgramStateRef State = N->getState();
877 auto *LCtx = N->getLocationContext();
878 if (!S)
879 return None;
880
881 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
882 if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
883 if (const Expr *RHS = VD->getInit())
884 if (RegionOfInterest->isSubRegionOf(
885 State->getLValue(VD, LCtx).getAsRegion()))
886 return RHS->getBeginLoc();
887 } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
888 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
889 const Expr *RHS = BO->getRHS();
890 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
891 return RHS->getBeginLoc();
892 }
893 }
894 return None;
895 }
896 };
897
898 } // end of anonymous namespace
899
900 namespace {
901
902 /// Emits an extra note at the return statement of an interesting stack frame.
903 ///
904 /// The returned value is marked as an interesting value, and if it's null,
905 /// adds a visitor to track where it became null.
906 ///
907 /// This visitor is intended to be used when another visitor discovers that an
908 /// interesting value comes from an inlined function call.
909 class ReturnVisitor : public TrackingBugReporterVisitor {
910 const StackFrameContext *CalleeSFC;
911 enum {
912 Initial,
913 MaybeUnsuppress,
914 Satisfied
915 } Mode = Initial;
916
917 bool EnableNullFPSuppression;
918 bool ShouldInvalidate = true;
919 AnalyzerOptions& Options;
920 bugreporter::TrackingKind TKind;
921
922 public:
ReturnVisitor(TrackerRef ParentTracker,const StackFrameContext * Frame,bool Suppressed,AnalyzerOptions & Options,bugreporter::TrackingKind TKind)923 ReturnVisitor(TrackerRef ParentTracker, const StackFrameContext *Frame,
924 bool Suppressed, AnalyzerOptions &Options,
925 bugreporter::TrackingKind TKind)
926 : TrackingBugReporterVisitor(ParentTracker), CalleeSFC(Frame),
927 EnableNullFPSuppression(Suppressed), Options(Options), TKind(TKind) {}
928
getTag()929 static void *getTag() {
930 static int Tag = 0;
931 return static_cast<void *>(&Tag);
932 }
933
Profile(llvm::FoldingSetNodeID & ID) const934 void Profile(llvm::FoldingSetNodeID &ID) const override {
935 ID.AddPointer(ReturnVisitor::getTag());
936 ID.AddPointer(CalleeSFC);
937 ID.AddBoolean(EnableNullFPSuppression);
938 }
939
visitNodeInitial(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)940 PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
941 BugReporterContext &BRC,
942 PathSensitiveBugReport &BR) {
943 // Only print a message at the interesting return statement.
944 if (N->getLocationContext() != CalleeSFC)
945 return nullptr;
946
947 Optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
948 if (!SP)
949 return nullptr;
950
951 const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt());
952 if (!Ret)
953 return nullptr;
954
955 // Okay, we're at the right return statement, but do we have the return
956 // value available?
957 ProgramStateRef State = N->getState();
958 SVal V = State->getSVal(Ret, CalleeSFC);
959 if (V.isUnknownOrUndef())
960 return nullptr;
961
962 // Don't print any more notes after this one.
963 Mode = Satisfied;
964
965 const Expr *RetE = Ret->getRetValue();
966 assert(RetE && "Tracking a return value for a void function");
967
968 // Handle cases where a reference is returned and then immediately used.
969 Optional<Loc> LValue;
970 if (RetE->isGLValue()) {
971 if ((LValue = V.getAs<Loc>())) {
972 SVal RValue = State->getRawSVal(*LValue, RetE->getType());
973 if (RValue.getAs<DefinedSVal>())
974 V = RValue;
975 }
976 }
977
978 // Ignore aggregate rvalues.
979 if (V.getAs<nonloc::LazyCompoundVal>() ||
980 V.getAs<nonloc::CompoundVal>())
981 return nullptr;
982
983 RetE = RetE->IgnoreParenCasts();
984
985 // Let's track the return value.
986 getParentTracker().track(RetE, N, {TKind, EnableNullFPSuppression});
987
988 // Build an appropriate message based on the return value.
989 SmallString<64> Msg;
990 llvm::raw_svector_ostream Out(Msg);
991
992 bool WouldEventBeMeaningless = false;
993
994 if (State->isNull(V).isConstrainedTrue()) {
995 if (V.getAs<Loc>()) {
996
997 // If we have counter-suppression enabled, make sure we keep visiting
998 // future nodes. We want to emit a path note as well, in case
999 // the report is resurrected as valid later on.
1000 if (EnableNullFPSuppression &&
1001 Options.ShouldAvoidSuppressingNullArgumentPaths)
1002 Mode = MaybeUnsuppress;
1003
1004 if (RetE->getType()->isObjCObjectPointerType()) {
1005 Out << "Returning nil";
1006 } else {
1007 Out << "Returning null pointer";
1008 }
1009 } else {
1010 Out << "Returning zero";
1011 }
1012
1013 } else {
1014 if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
1015 Out << "Returning the value " << CI->getValue();
1016 } else {
1017 // There is nothing interesting about returning a value, when it is
1018 // plain value without any constraints, and the function is guaranteed
1019 // to return that every time. We could use CFG::isLinear() here, but
1020 // constexpr branches are obvious to the compiler, not necesserily to
1021 // the programmer.
1022 if (N->getCFG().size() == 3)
1023 WouldEventBeMeaningless = true;
1024
1025 if (V.getAs<Loc>())
1026 Out << "Returning pointer";
1027 else
1028 Out << "Returning value";
1029 }
1030 }
1031
1032 if (LValue) {
1033 if (const MemRegion *MR = LValue->getAsRegion()) {
1034 if (MR->canPrintPretty()) {
1035 Out << " (reference to ";
1036 MR->printPretty(Out);
1037 Out << ")";
1038 }
1039 }
1040 } else {
1041 // FIXME: We should have a more generalized location printing mechanism.
1042 if (const auto *DR = dyn_cast<DeclRefExpr>(RetE))
1043 if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
1044 Out << " (loaded from '" << *DD << "')";
1045 }
1046
1047 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), CalleeSFC);
1048 if (!L.isValid() || !L.asLocation().isValid())
1049 return nullptr;
1050
1051 if (TKind == bugreporter::TrackingKind::Condition)
1052 Out << WillBeUsedForACondition;
1053
1054 auto EventPiece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1055
1056 // If we determined that the note is meaningless, make it prunable, and
1057 // don't mark the stackframe interesting.
1058 if (WouldEventBeMeaningless)
1059 EventPiece->setPrunable(true);
1060 else
1061 BR.markInteresting(CalleeSFC);
1062
1063 return EventPiece;
1064 }
1065
visitNodeMaybeUnsuppress(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)1066 PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N,
1067 BugReporterContext &BRC,
1068 PathSensitiveBugReport &BR) {
1069 assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
1070
1071 // Are we at the entry node for this call?
1072 Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
1073 if (!CE)
1074 return nullptr;
1075
1076 if (CE->getCalleeContext() != CalleeSFC)
1077 return nullptr;
1078
1079 Mode = Satisfied;
1080
1081 // Don't automatically suppress a report if one of the arguments is
1082 // known to be a null pointer. Instead, start tracking /that/ null
1083 // value back to its origin.
1084 ProgramStateManager &StateMgr = BRC.getStateManager();
1085 CallEventManager &CallMgr = StateMgr.getCallEventManager();
1086
1087 ProgramStateRef State = N->getState();
1088 CallEventRef<> Call = CallMgr.getCaller(CalleeSFC, State);
1089 for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
1090 Optional<Loc> ArgV = Call->getArgSVal(I).getAs<Loc>();
1091 if (!ArgV)
1092 continue;
1093
1094 const Expr *ArgE = Call->getArgExpr(I);
1095 if (!ArgE)
1096 continue;
1097
1098 // Is it possible for this argument to be non-null?
1099 if (!State->isNull(*ArgV).isConstrainedTrue())
1100 continue;
1101
1102 if (getParentTracker()
1103 .track(ArgE, N, {TKind, EnableNullFPSuppression})
1104 .FoundSomethingToTrack)
1105 ShouldInvalidate = false;
1106
1107 // If we /can't/ track the null pointer, we should err on the side of
1108 // false negatives, and continue towards marking this report invalid.
1109 // (We will still look at the other arguments, though.)
1110 }
1111
1112 return nullptr;
1113 }
1114
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)1115 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1116 BugReporterContext &BRC,
1117 PathSensitiveBugReport &BR) override {
1118 switch (Mode) {
1119 case Initial:
1120 return visitNodeInitial(N, BRC, BR);
1121 case MaybeUnsuppress:
1122 return visitNodeMaybeUnsuppress(N, BRC, BR);
1123 case Satisfied:
1124 return nullptr;
1125 }
1126
1127 llvm_unreachable("Invalid visit mode!");
1128 }
1129
finalizeVisitor(BugReporterContext &,const ExplodedNode *,PathSensitiveBugReport & BR)1130 void finalizeVisitor(BugReporterContext &, const ExplodedNode *,
1131 PathSensitiveBugReport &BR) override {
1132 if (EnableNullFPSuppression && ShouldInvalidate)
1133 BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC);
1134 }
1135 };
1136
1137 } // end of anonymous namespace
1138
1139 //===----------------------------------------------------------------------===//
1140 // StoreSiteFinder
1141 //===----------------------------------------------------------------------===//
1142
1143 /// Finds last store into the given region,
1144 /// which is different from a given symbolic value.
1145 class StoreSiteFinder final : public TrackingBugReporterVisitor {
1146 const MemRegion *R;
1147 SVal V;
1148 bool Satisfied = false;
1149
1150 TrackingOptions Options;
1151 const StackFrameContext *OriginSFC;
1152
1153 public:
1154 /// \param V We're searching for the store where \c R received this value.
1155 /// \param R The region we're tracking.
1156 /// \param TKind May limit the amount of notes added to the bug report.
1157 /// \param OriginSFC Only adds notes when the last store happened in a
1158 /// different stackframe to this one. Disregarded if the tracking kind
1159 /// is thorough.
1160 /// This is useful, because for non-tracked regions, notes about
1161 /// changes to its value in a nested stackframe could be pruned, and
1162 /// this visitor can prevent that without polluting the bugpath too
1163 /// much.
StoreSiteFinder(bugreporter::TrackerRef ParentTracker,KnownSVal V,const MemRegion * R,TrackingOptions Options,const StackFrameContext * OriginSFC=nullptr)1164 StoreSiteFinder(bugreporter::TrackerRef ParentTracker, KnownSVal V,
1165 const MemRegion *R, TrackingOptions Options,
1166 const StackFrameContext *OriginSFC = nullptr)
1167 : TrackingBugReporterVisitor(ParentTracker), R(R), V(V), Options(Options),
1168 OriginSFC(OriginSFC) {
1169 assert(R);
1170 }
1171
1172 void Profile(llvm::FoldingSetNodeID &ID) const override;
1173
1174 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1175 BugReporterContext &BRC,
1176 PathSensitiveBugReport &BR) override;
1177 };
1178
Profile(llvm::FoldingSetNodeID & ID) const1179 void StoreSiteFinder::Profile(llvm::FoldingSetNodeID &ID) const {
1180 static int tag = 0;
1181 ID.AddPointer(&tag);
1182 ID.AddPointer(R);
1183 ID.Add(V);
1184 ID.AddInteger(static_cast<int>(Options.Kind));
1185 ID.AddBoolean(Options.EnableNullFPSuppression);
1186 }
1187
1188 /// Returns true if \p N represents the DeclStmt declaring and initializing
1189 /// \p VR.
isInitializationOfVar(const ExplodedNode * N,const VarRegion * VR)1190 static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
1191 Optional<PostStmt> P = N->getLocationAs<PostStmt>();
1192 if (!P)
1193 return false;
1194
1195 const DeclStmt *DS = P->getStmtAs<DeclStmt>();
1196 if (!DS)
1197 return false;
1198
1199 if (DS->getSingleDecl() != VR->getDecl())
1200 return false;
1201
1202 const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1203 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1204 if (!FrameSpace) {
1205 // If we ever directly evaluate global DeclStmts, this assertion will be
1206 // invalid, but this still seems preferable to silently accepting an
1207 // initialization that may be for a path-sensitive variable.
1208 assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
1209 return true;
1210 }
1211
1212 assert(VR->getDecl()->hasLocalStorage());
1213 const LocationContext *LCtx = N->getLocationContext();
1214 return FrameSpace->getStackFrame() == LCtx->getStackFrame();
1215 }
1216
isObjCPointer(const MemRegion * R)1217 static bool isObjCPointer(const MemRegion *R) {
1218 if (R->isBoundable())
1219 if (const auto *TR = dyn_cast<TypedValueRegion>(R))
1220 return TR->getValueType()->isObjCObjectPointerType();
1221
1222 return false;
1223 }
1224
isObjCPointer(const ValueDecl * D)1225 static bool isObjCPointer(const ValueDecl *D) {
1226 return D->getType()->isObjCObjectPointerType();
1227 }
1228
1229 /// Show diagnostics for initializing or declaring a region \p R with a bad value.
showBRDiagnostics(llvm::raw_svector_ostream & OS,StoreInfo SI)1230 static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) {
1231 const bool HasPrefix = SI.Dest->canPrintPretty();
1232
1233 if (HasPrefix) {
1234 SI.Dest->printPretty(OS);
1235 OS << " ";
1236 }
1237
1238 const char *Action = nullptr;
1239
1240 switch (SI.StoreKind) {
1241 case StoreInfo::Initialization:
1242 Action = HasPrefix ? "initialized to " : "Initializing to ";
1243 break;
1244 case StoreInfo::BlockCapture:
1245 Action = HasPrefix ? "captured by block as " : "Captured by block as ";
1246 break;
1247 default:
1248 llvm_unreachable("Unexpected store kind");
1249 }
1250
1251 if (SI.Value.getAs<loc::ConcreteInt>()) {
1252 OS << Action << (isObjCPointer(SI.Dest) ? "nil" : "a null pointer value");
1253
1254 } else if (auto CVal = SI.Value.getAs<nonloc::ConcreteInt>()) {
1255 OS << Action << CVal->getValue();
1256
1257 } else if (SI.Origin && SI.Origin->canPrintPretty()) {
1258 OS << Action << "the value of ";
1259 SI.Origin->printPretty(OS);
1260
1261 } else if (SI.StoreKind == StoreInfo::Initialization) {
1262 // We don't need to check here, all these conditions were
1263 // checked by StoreSiteFinder, when it figured out that it is
1264 // initialization.
1265 const auto *DS =
1266 cast<DeclStmt>(SI.StoreSite->getLocationAs<PostStmt>()->getStmt());
1267
1268 if (SI.Value.isUndef()) {
1269 if (isa<VarRegion>(SI.Dest)) {
1270 const auto *VD = cast<VarDecl>(DS->getSingleDecl());
1271
1272 if (VD->getInit()) {
1273 OS << (HasPrefix ? "initialized" : "Initializing")
1274 << " to a garbage value";
1275 } else {
1276 OS << (HasPrefix ? "declared" : "Declaring")
1277 << " without an initial value";
1278 }
1279 }
1280 } else {
1281 OS << (HasPrefix ? "initialized" : "Initialized") << " here";
1282 }
1283 }
1284 }
1285
1286 /// Display diagnostics for passing bad region as a parameter.
showBRParamDiagnostics(llvm::raw_svector_ostream & OS,StoreInfo SI)1287 static void showBRParamDiagnostics(llvm::raw_svector_ostream &OS,
1288 StoreInfo SI) {
1289 const auto *VR = cast<VarRegion>(SI.Dest);
1290 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1291
1292 OS << "Passing ";
1293
1294 if (SI.Value.getAs<loc::ConcreteInt>()) {
1295 OS << (isObjCPointer(Param) ? "nil object reference"
1296 : "null pointer value");
1297
1298 } else if (SI.Value.isUndef()) {
1299 OS << "uninitialized value";
1300
1301 } else if (auto CI = SI.Value.getAs<nonloc::ConcreteInt>()) {
1302 OS << "the value " << CI->getValue();
1303
1304 } else if (SI.Origin && SI.Origin->canPrintPretty()) {
1305 SI.Origin->printPretty(OS);
1306
1307 } else {
1308 OS << "value";
1309 }
1310
1311 // Printed parameter indexes are 1-based, not 0-based.
1312 unsigned Idx = Param->getFunctionScopeIndex() + 1;
1313 OS << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
1314 if (VR->canPrintPretty()) {
1315 OS << " ";
1316 VR->printPretty(OS);
1317 }
1318 }
1319
1320 /// Show default diagnostics for storing bad region.
showBRDefaultDiagnostics(llvm::raw_svector_ostream & OS,StoreInfo SI)1321 static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &OS,
1322 StoreInfo SI) {
1323 const bool HasSuffix = SI.Dest->canPrintPretty();
1324
1325 if (SI.Value.getAs<loc::ConcreteInt>()) {
1326 OS << (isObjCPointer(SI.Dest) ? "nil object reference stored"
1327 : (HasSuffix ? "Null pointer value stored"
1328 : "Storing null pointer value"));
1329
1330 } else if (SI.Value.isUndef()) {
1331 OS << (HasSuffix ? "Uninitialized value stored"
1332 : "Storing uninitialized value");
1333
1334 } else if (auto CV = SI.Value.getAs<nonloc::ConcreteInt>()) {
1335 if (HasSuffix)
1336 OS << "The value " << CV->getValue() << " is assigned";
1337 else
1338 OS << "Assigning " << CV->getValue();
1339
1340 } else if (SI.Origin && SI.Origin->canPrintPretty()) {
1341 if (HasSuffix) {
1342 OS << "The value of ";
1343 SI.Origin->printPretty(OS);
1344 OS << " is assigned";
1345 } else {
1346 OS << "Assigning the value of ";
1347 SI.Origin->printPretty(OS);
1348 }
1349
1350 } else {
1351 OS << (HasSuffix ? "Value assigned" : "Assigning value");
1352 }
1353
1354 if (HasSuffix) {
1355 OS << " to ";
1356 SI.Dest->printPretty(OS);
1357 }
1358 }
1359
VisitNode(const ExplodedNode * Succ,BugReporterContext & BRC,PathSensitiveBugReport & BR)1360 PathDiagnosticPieceRef StoreSiteFinder::VisitNode(const ExplodedNode *Succ,
1361 BugReporterContext &BRC,
1362 PathSensitiveBugReport &BR) {
1363 if (Satisfied)
1364 return nullptr;
1365
1366 const ExplodedNode *StoreSite = nullptr;
1367 const ExplodedNode *Pred = Succ->getFirstPred();
1368 const Expr *InitE = nullptr;
1369 bool IsParam = false;
1370
1371 // First see if we reached the declaration of the region.
1372 if (const auto *VR = dyn_cast<VarRegion>(R)) {
1373 if (isInitializationOfVar(Pred, VR)) {
1374 StoreSite = Pred;
1375 InitE = VR->getDecl()->getInit();
1376 }
1377 }
1378
1379 // If this is a post initializer expression, initializing the region, we
1380 // should track the initializer expression.
1381 if (Optional<PostInitializer> PIP = Pred->getLocationAs<PostInitializer>()) {
1382 const MemRegion *FieldReg = (const MemRegion *)PIP->getLocationValue();
1383 if (FieldReg == R) {
1384 StoreSite = Pred;
1385 InitE = PIP->getInitializer()->getInit();
1386 }
1387 }
1388
1389 // Otherwise, see if this is the store site:
1390 // (1) Succ has this binding and Pred does not, i.e. this is
1391 // where the binding first occurred.
1392 // (2) Succ has this binding and is a PostStore node for this region, i.e.
1393 // the same binding was re-assigned here.
1394 if (!StoreSite) {
1395 if (Succ->getState()->getSVal(R) != V)
1396 return nullptr;
1397
1398 if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) {
1399 Optional<PostStore> PS = Succ->getLocationAs<PostStore>();
1400 if (!PS || PS->getLocationValue() != R)
1401 return nullptr;
1402 }
1403
1404 StoreSite = Succ;
1405
1406 // If this is an assignment expression, we can track the value
1407 // being assigned.
1408 if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>())
1409 if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>())
1410 if (BO->isAssignmentOp())
1411 InitE = BO->getRHS();
1412
1413 // If this is a call entry, the variable should be a parameter.
1414 // FIXME: Handle CXXThisRegion as well. (This is not a priority because
1415 // 'this' should never be NULL, but this visitor isn't just for NULL and
1416 // UndefinedVal.)
1417 if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
1418 if (const auto *VR = dyn_cast<VarRegion>(R)) {
1419
1420 if (const auto *Param = dyn_cast<ParmVarDecl>(VR->getDecl())) {
1421 ProgramStateManager &StateMgr = BRC.getStateManager();
1422 CallEventManager &CallMgr = StateMgr.getCallEventManager();
1423
1424 CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
1425 Succ->getState());
1426 InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1427 } else {
1428 // Handle Objective-C 'self'.
1429 assert(isa<ImplicitParamDecl>(VR->getDecl()));
1430 InitE = cast<ObjCMessageExpr>(CE->getCalleeContext()->getCallSite())
1431 ->getInstanceReceiver()->IgnoreParenCasts();
1432 }
1433 IsParam = true;
1434 }
1435 }
1436
1437 // If this is a CXXTempObjectRegion, the Expr responsible for its creation
1438 // is wrapped inside of it.
1439 if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1440 InitE = TmpR->getExpr();
1441 }
1442
1443 if (!StoreSite)
1444 return nullptr;
1445
1446 Satisfied = true;
1447
1448 // If we have an expression that provided the value, try to track where it
1449 // came from.
1450 if (InitE) {
1451 if (!IsParam)
1452 InitE = InitE->IgnoreParenCasts();
1453
1454 getParentTracker().track(InitE, StoreSite, Options);
1455 }
1456
1457 // Let's try to find the region where the value came from.
1458 const MemRegion *OldRegion = nullptr;
1459
1460 // If we have init expression, it might be simply a reference
1461 // to a variable, so we can use it.
1462 if (InitE) {
1463 // That region might still be not exactly what we are looking for.
1464 // In situations like `int &ref = val;`, we can't say that
1465 // `ref` is initialized with `val`, rather refers to `val`.
1466 //
1467 // In order, to mitigate situations like this, we check if the last
1468 // stored value in that region is the value that we track.
1469 //
1470 // TODO: support other situations better.
1471 if (const MemRegion *Candidate =
1472 getLocationRegionIfReference(InitE, Succ, false)) {
1473 const StoreManager &SM = BRC.getStateManager().getStoreManager();
1474
1475 // Here we traverse the graph up to find the last node where the
1476 // candidate region is still in the store.
1477 for (const ExplodedNode *N = StoreSite; N; N = N->getFirstPred()) {
1478 if (SM.includedInBindings(N->getState()->getStore(), Candidate)) {
1479 // And if it was bound to the target value, we can use it.
1480 if (N->getState()->getSVal(Candidate) == V) {
1481 OldRegion = Candidate;
1482 }
1483 break;
1484 }
1485 }
1486 }
1487 }
1488
1489 // Otherwise, if the current region does indeed contain the value
1490 // we are looking for, we can look for a region where this value
1491 // was before.
1492 //
1493 // It can be useful for situations like:
1494 // new = identity(old)
1495 // where the analyzer knows that 'identity' returns the value of its
1496 // first argument.
1497 //
1498 // NOTE: If the region R is not a simple var region, it can contain
1499 // V in one of its subregions.
1500 if (!OldRegion && StoreSite->getState()->getSVal(R) == V) {
1501 // Let's go up the graph to find the node where the region is
1502 // bound to V.
1503 const ExplodedNode *NodeWithoutBinding = StoreSite->getFirstPred();
1504 for (;
1505 NodeWithoutBinding && NodeWithoutBinding->getState()->getSVal(R) == V;
1506 NodeWithoutBinding = NodeWithoutBinding->getFirstPred()) {
1507 }
1508
1509 if (NodeWithoutBinding) {
1510 // Let's try to find a unique binding for the value in that node.
1511 // We want to use this to find unique bindings because of the following
1512 // situations:
1513 // b = a;
1514 // c = identity(b);
1515 //
1516 // Telling the user that the value of 'a' is assigned to 'c', while
1517 // correct, can be confusing.
1518 StoreManager::FindUniqueBinding FB(V.getAsLocSymbol());
1519 BRC.getStateManager().iterBindings(NodeWithoutBinding->getState(), FB);
1520 if (FB)
1521 OldRegion = FB.getRegion();
1522 }
1523 }
1524
1525 if (Options.Kind == TrackingKind::Condition && OriginSFC &&
1526 !OriginSFC->isParentOf(StoreSite->getStackFrame()))
1527 return nullptr;
1528
1529 // Okay, we've found the binding. Emit an appropriate message.
1530 SmallString<256> sbuf;
1531 llvm::raw_svector_ostream os(sbuf);
1532
1533 StoreInfo SI = {StoreInfo::Assignment, // default kind
1534 StoreSite,
1535 InitE,
1536 V,
1537 R,
1538 OldRegion};
1539
1540 if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
1541 const Stmt *S = PS->getStmt();
1542 const auto *DS = dyn_cast<DeclStmt>(S);
1543 const auto *VR = dyn_cast<VarRegion>(R);
1544
1545 if (DS) {
1546 SI.StoreKind = StoreInfo::Initialization;
1547 } else if (isa<BlockExpr>(S)) {
1548 SI.StoreKind = StoreInfo::BlockCapture;
1549 if (VR) {
1550 // See if we can get the BlockVarRegion.
1551 ProgramStateRef State = StoreSite->getState();
1552 SVal V = StoreSite->getSVal(S);
1553 if (const auto *BDR =
1554 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1555 if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1556 getParentTracker().track(State->getSVal(OriginalR), OriginalR,
1557 Options, OriginSFC);
1558 }
1559 }
1560 }
1561 }
1562 } else if (SI.StoreSite->getLocation().getAs<CallEnter>() &&
1563 isa<VarRegion>(SI.Dest)) {
1564 SI.StoreKind = StoreInfo::CallArgument;
1565 }
1566
1567 return getParentTracker().handle(SI, BRC, Options);
1568 }
1569
1570 //===----------------------------------------------------------------------===//
1571 // Implementation of TrackConstraintBRVisitor.
1572 //===----------------------------------------------------------------------===//
1573
Profile(llvm::FoldingSetNodeID & ID) const1574 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
1575 static int tag = 0;
1576 ID.AddPointer(&tag);
1577 ID.AddBoolean(Assumption);
1578 ID.Add(Constraint);
1579 }
1580
1581 /// Return the tag associated with this visitor. This tag will be used
1582 /// to make all PathDiagnosticPieces created by this visitor.
getTag()1583 const char *TrackConstraintBRVisitor::getTag() {
1584 return "TrackConstraintBRVisitor";
1585 }
1586
isUnderconstrained(const ExplodedNode * N) const1587 bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
1588 if (IsZeroCheck)
1589 return N->getState()->isNull(Constraint).isUnderconstrained();
1590 return (bool)N->getState()->assume(Constraint, !Assumption);
1591 }
1592
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport &)1593 PathDiagnosticPieceRef TrackConstraintBRVisitor::VisitNode(
1594 const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
1595 const ExplodedNode *PrevN = N->getFirstPred();
1596 if (IsSatisfied)
1597 return nullptr;
1598
1599 // Start tracking after we see the first state in which the value is
1600 // constrained.
1601 if (!IsTrackingTurnedOn)
1602 if (!isUnderconstrained(N))
1603 IsTrackingTurnedOn = true;
1604 if (!IsTrackingTurnedOn)
1605 return nullptr;
1606
1607 // Check if in the previous state it was feasible for this constraint
1608 // to *not* be true.
1609 if (isUnderconstrained(PrevN)) {
1610 IsSatisfied = true;
1611
1612 // As a sanity check, make sure that the negation of the constraint
1613 // was infeasible in the current state. If it is feasible, we somehow
1614 // missed the transition point.
1615 assert(!isUnderconstrained(N));
1616
1617 // We found the transition point for the constraint. We now need to
1618 // pretty-print the constraint. (work-in-progress)
1619 SmallString<64> sbuf;
1620 llvm::raw_svector_ostream os(sbuf);
1621
1622 if (Constraint.getAs<Loc>()) {
1623 os << "Assuming pointer value is ";
1624 os << (Assumption ? "non-null" : "null");
1625 }
1626
1627 if (os.str().empty())
1628 return nullptr;
1629
1630 // Construct a new PathDiagnosticPiece.
1631 ProgramPoint P = N->getLocation();
1632 PathDiagnosticLocation L =
1633 PathDiagnosticLocation::create(P, BRC.getSourceManager());
1634 if (!L.isValid())
1635 return nullptr;
1636
1637 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1638 X->setTag(getTag());
1639 return std::move(X);
1640 }
1641
1642 return nullptr;
1643 }
1644
1645 //===----------------------------------------------------------------------===//
1646 // Implementation of SuppressInlineDefensiveChecksVisitor.
1647 //===----------------------------------------------------------------------===//
1648
1649 SuppressInlineDefensiveChecksVisitor::
SuppressInlineDefensiveChecksVisitor(DefinedSVal Value,const ExplodedNode * N)1650 SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
1651 : V(Value) {
1652 // Check if the visitor is disabled.
1653 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1654 if (!Options.ShouldSuppressInlinedDefensiveChecks)
1655 IsSatisfied = true;
1656 }
1657
Profile(llvm::FoldingSetNodeID & ID) const1658 void SuppressInlineDefensiveChecksVisitor::Profile(
1659 llvm::FoldingSetNodeID &ID) const {
1660 static int id = 0;
1661 ID.AddPointer(&id);
1662 ID.Add(V);
1663 }
1664
getTag()1665 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1666 return "IDCVisitor";
1667 }
1668
1669 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * Succ,BugReporterContext & BRC,PathSensitiveBugReport & BR)1670 SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
1671 BugReporterContext &BRC,
1672 PathSensitiveBugReport &BR) {
1673 const ExplodedNode *Pred = Succ->getFirstPred();
1674 if (IsSatisfied)
1675 return nullptr;
1676
1677 // Start tracking after we see the first state in which the value is null.
1678 if (!IsTrackingTurnedOn)
1679 if (Succ->getState()->isNull(V).isConstrainedTrue())
1680 IsTrackingTurnedOn = true;
1681 if (!IsTrackingTurnedOn)
1682 return nullptr;
1683
1684 // Check if in the previous state it was feasible for this value
1685 // to *not* be null.
1686 if (!Pred->getState()->isNull(V).isConstrainedTrue() &&
1687 Succ->getState()->isNull(V).isConstrainedTrue()) {
1688 IsSatisfied = true;
1689
1690 // Check if this is inlined defensive checks.
1691 const LocationContext *CurLC = Succ->getLocationContext();
1692 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1693 if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
1694 BR.markInvalid("Suppress IDC", CurLC);
1695 return nullptr;
1696 }
1697
1698 // Treat defensive checks in function-like macros as if they were an inlined
1699 // defensive check. If the bug location is not in a macro and the
1700 // terminator for the current location is in a macro then suppress the
1701 // warning.
1702 auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>();
1703
1704 if (!BugPoint)
1705 return nullptr;
1706
1707 ProgramPoint CurPoint = Succ->getLocation();
1708 const Stmt *CurTerminatorStmt = nullptr;
1709 if (auto BE = CurPoint.getAs<BlockEdge>()) {
1710 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1711 } else if (auto SP = CurPoint.getAs<StmtPoint>()) {
1712 const Stmt *CurStmt = SP->getStmt();
1713 if (!CurStmt->getBeginLoc().isMacroID())
1714 return nullptr;
1715
1716 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1717 CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt();
1718 } else {
1719 return nullptr;
1720 }
1721
1722 if (!CurTerminatorStmt)
1723 return nullptr;
1724
1725 SourceLocation TerminatorLoc = CurTerminatorStmt->getBeginLoc();
1726 if (TerminatorLoc.isMacroID()) {
1727 SourceLocation BugLoc = BugPoint->getStmt()->getBeginLoc();
1728
1729 // Suppress reports unless we are in that same macro.
1730 if (!BugLoc.isMacroID() ||
1731 getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) {
1732 BR.markInvalid("Suppress Macro IDC", CurLC);
1733 }
1734 return nullptr;
1735 }
1736 }
1737 return nullptr;
1738 }
1739
1740 //===----------------------------------------------------------------------===//
1741 // TrackControlDependencyCondBRVisitor.
1742 //===----------------------------------------------------------------------===//
1743
1744 namespace {
1745 /// Tracks the expressions that are a control dependency of the node that was
1746 /// supplied to the constructor.
1747 /// For example:
1748 ///
1749 /// cond = 1;
1750 /// if (cond)
1751 /// 10 / 0;
1752 ///
1753 /// An error is emitted at line 3. This visitor realizes that the branch
1754 /// on line 2 is a control dependency of line 3, and tracks it's condition via
1755 /// trackExpressionValue().
1756 class TrackControlDependencyCondBRVisitor final
1757 : public TrackingBugReporterVisitor {
1758 const ExplodedNode *Origin;
1759 ControlDependencyCalculator ControlDeps;
1760 llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1761
1762 public:
TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker,const ExplodedNode * O)1763 TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker,
1764 const ExplodedNode *O)
1765 : TrackingBugReporterVisitor(ParentTracker), Origin(O),
1766 ControlDeps(&O->getCFG()) {}
1767
Profile(llvm::FoldingSetNodeID & ID) const1768 void Profile(llvm::FoldingSetNodeID &ID) const override {
1769 static int x = 0;
1770 ID.AddPointer(&x);
1771 }
1772
1773 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1774 BugReporterContext &BRC,
1775 PathSensitiveBugReport &BR) override;
1776 };
1777 } // end of anonymous namespace
1778
1779 static std::shared_ptr<PathDiagnosticEventPiece>
constructDebugPieceForTrackedCondition(const Expr * Cond,const ExplodedNode * N,BugReporterContext & BRC)1780 constructDebugPieceForTrackedCondition(const Expr *Cond,
1781 const ExplodedNode *N,
1782 BugReporterContext &BRC) {
1783
1784 if (BRC.getAnalyzerOptions().AnalysisDiagOpt == PD_NONE ||
1785 !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1786 return nullptr;
1787
1788 std::string ConditionText = std::string(Lexer::getSourceText(
1789 CharSourceRange::getTokenRange(Cond->getSourceRange()),
1790 BRC.getSourceManager(), BRC.getASTContext().getLangOpts()));
1791
1792 return std::make_shared<PathDiagnosticEventPiece>(
1793 PathDiagnosticLocation::createBegin(
1794 Cond, BRC.getSourceManager(), N->getLocationContext()),
1795 (Twine() + "Tracking condition '" + ConditionText + "'").str());
1796 }
1797
isAssertlikeBlock(const CFGBlock * B,ASTContext & Context)1798 static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
1799 if (B->succ_size() != 2)
1800 return false;
1801
1802 const CFGBlock *Then = B->succ_begin()->getReachableBlock();
1803 const CFGBlock *Else = (B->succ_begin() + 1)->getReachableBlock();
1804
1805 if (!Then || !Else)
1806 return false;
1807
1808 if (Then->isInevitablySinking() != Else->isInevitablySinking())
1809 return true;
1810
1811 // For the following condition the following CFG would be built:
1812 //
1813 // ------------->
1814 // / \
1815 // [B1] -> [B2] -> [B3] -> [sink]
1816 // assert(A && B || C); \ \
1817 // -----------> [go on with the execution]
1818 //
1819 // It so happens that CFGBlock::getTerminatorCondition returns 'A' for block
1820 // B1, 'A && B' for B2, and 'A && B || C' for B3. Let's check whether we
1821 // reached the end of the condition!
1822 if (const Stmt *ElseCond = Else->getTerminatorCondition())
1823 if (const auto *BinOp = dyn_cast<BinaryOperator>(ElseCond))
1824 if (BinOp->isLogicalOp())
1825 return isAssertlikeBlock(Else, Context);
1826
1827 return false;
1828 }
1829
1830 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)1831 TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
1832 BugReporterContext &BRC,
1833 PathSensitiveBugReport &BR) {
1834 // We can only reason about control dependencies within the same stack frame.
1835 if (Origin->getStackFrame() != N->getStackFrame())
1836 return nullptr;
1837
1838 CFGBlock *NB = const_cast<CFGBlock *>(N->getCFGBlock());
1839
1840 // Skip if we already inspected this block.
1841 if (!VisitedBlocks.insert(NB).second)
1842 return nullptr;
1843
1844 CFGBlock *OriginB = const_cast<CFGBlock *>(Origin->getCFGBlock());
1845
1846 // TODO: Cache CFGBlocks for each ExplodedNode.
1847 if (!OriginB || !NB)
1848 return nullptr;
1849
1850 if (isAssertlikeBlock(NB, BRC.getASTContext()))
1851 return nullptr;
1852
1853 if (ControlDeps.isControlDependent(OriginB, NB)) {
1854 // We don't really want to explain for range loops. Evidence suggests that
1855 // the only thing that leads to is the addition of calls to operator!=.
1856 if (llvm::isa_and_nonnull<CXXForRangeStmt>(NB->getTerminatorStmt()))
1857 return nullptr;
1858
1859 if (const Expr *Condition = NB->getLastCondition()) {
1860 // Keeping track of the already tracked conditions on a visitor level
1861 // isn't sufficient, because a new visitor is created for each tracked
1862 // expression, hence the BugReport level set.
1863 if (BR.addTrackedCondition(N)) {
1864 getParentTracker().track(Condition, N,
1865 {bugreporter::TrackingKind::Condition,
1866 /*EnableNullFPSuppression=*/false});
1867 return constructDebugPieceForTrackedCondition(Condition, N, BRC);
1868 }
1869 }
1870 }
1871
1872 return nullptr;
1873 }
1874
1875 //===----------------------------------------------------------------------===//
1876 // Implementation of trackExpressionValue.
1877 //===----------------------------------------------------------------------===//
1878
1879 /// \return A subexpression of @c Ex which represents the
1880 /// expression-of-interest.
peelOffOuterExpr(const Expr * Ex,const ExplodedNode * N)1881 static const Expr *peelOffOuterExpr(const Expr *Ex,
1882 const ExplodedNode *N) {
1883 Ex = Ex->IgnoreParenCasts();
1884 if (const auto *FE = dyn_cast<FullExpr>(Ex))
1885 return peelOffOuterExpr(FE->getSubExpr(), N);
1886 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1887 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1888 if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1889 const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
1890 if (PropRef && PropRef->isMessagingGetter()) {
1891 const Expr *GetterMessageSend =
1892 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1893 assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
1894 return peelOffOuterExpr(GetterMessageSend, N);
1895 }
1896 }
1897
1898 // Peel off the ternary operator.
1899 if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1900 // Find a node where the branching occurred and find out which branch
1901 // we took (true/false) by looking at the ExplodedGraph.
1902 const ExplodedNode *NI = N;
1903 do {
1904 ProgramPoint ProgPoint = NI->getLocation();
1905 if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
1906 const CFGBlock *srcBlk = BE->getSrc();
1907 if (const Stmt *term = srcBlk->getTerminatorStmt()) {
1908 if (term == CO) {
1909 bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst());
1910 if (TookTrueBranch)
1911 return peelOffOuterExpr(CO->getTrueExpr(), N);
1912 else
1913 return peelOffOuterExpr(CO->getFalseExpr(), N);
1914 }
1915 }
1916 }
1917 NI = NI->getFirstPred();
1918 } while (NI);
1919 }
1920
1921 if (auto *BO = dyn_cast<BinaryOperator>(Ex))
1922 if (const Expr *SubEx = peelOffPointerArithmetic(BO))
1923 return peelOffOuterExpr(SubEx, N);
1924
1925 if (auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1926 if (UO->getOpcode() == UO_LNot)
1927 return peelOffOuterExpr(UO->getSubExpr(), N);
1928
1929 // FIXME: There's a hack in our Store implementation that always computes
1930 // field offsets around null pointers as if they are always equal to 0.
1931 // The idea here is to report accesses to fields as null dereferences
1932 // even though the pointer value that's being dereferenced is actually
1933 // the offset of the field rather than exactly 0.
1934 // See the FIXME in StoreManager's getLValueFieldOrIvar() method.
1935 // This code interacts heavily with this hack; otherwise the value
1936 // would not be null at all for most fields, so we'd be unable to track it.
1937 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1938 if (const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1939 return peelOffOuterExpr(DerefEx, N);
1940 }
1941
1942 return Ex;
1943 }
1944
1945 /// Find the ExplodedNode where the lvalue (the value of 'Ex')
1946 /// was computed.
findNodeForExpression(const ExplodedNode * N,const Expr * Inner)1947 static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
1948 const Expr *Inner) {
1949 while (N) {
1950 if (N->getStmtForDiagnostics() == Inner)
1951 return N;
1952 N = N->getFirstPred();
1953 }
1954 return N;
1955 }
1956
1957 //===----------------------------------------------------------------------===//
1958 // Tracker implementation
1959 //===----------------------------------------------------------------------===//
1960
constructNote(StoreInfo SI,BugReporterContext & BRC,StringRef NodeText)1961 PathDiagnosticPieceRef StoreHandler::constructNote(StoreInfo SI,
1962 BugReporterContext &BRC,
1963 StringRef NodeText) {
1964 // Construct a new PathDiagnosticPiece.
1965 ProgramPoint P = SI.StoreSite->getLocation();
1966 PathDiagnosticLocation L;
1967 if (P.getAs<CallEnter>() && SI.SourceOfTheValue)
1968 L = PathDiagnosticLocation(SI.SourceOfTheValue, BRC.getSourceManager(),
1969 P.getLocationContext());
1970
1971 if (!L.isValid() || !L.asLocation().isValid())
1972 L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
1973
1974 if (!L.isValid() || !L.asLocation().isValid())
1975 return nullptr;
1976
1977 return std::make_shared<PathDiagnosticEventPiece>(L, NodeText);
1978 }
1979
1980 class DefaultStoreHandler final : public StoreHandler {
1981 public:
1982 using StoreHandler::StoreHandler;
1983
handle(StoreInfo SI,BugReporterContext & BRC,TrackingOptions Opts)1984 PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
1985 TrackingOptions Opts) override {
1986 // Okay, we've found the binding. Emit an appropriate message.
1987 SmallString<256> Buffer;
1988 llvm::raw_svector_ostream OS(Buffer);
1989
1990 switch (SI.StoreKind) {
1991 case StoreInfo::Initialization:
1992 case StoreInfo::BlockCapture:
1993 showBRDiagnostics(OS, SI);
1994 break;
1995 case StoreInfo::CallArgument:
1996 showBRParamDiagnostics(OS, SI);
1997 break;
1998 case StoreInfo::Assignment:
1999 showBRDefaultDiagnostics(OS, SI);
2000 break;
2001 }
2002
2003 if (Opts.Kind == bugreporter::TrackingKind::Condition)
2004 OS << WillBeUsedForACondition;
2005
2006 return constructNote(SI, BRC, OS.str());
2007 }
2008 };
2009
2010 class ControlDependencyHandler final : public ExpressionHandler {
2011 public:
2012 using ExpressionHandler::ExpressionHandler;
2013
handle(const Expr * Inner,const ExplodedNode * InputNode,const ExplodedNode * LVNode,TrackingOptions Opts)2014 Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2015 const ExplodedNode *LVNode,
2016 TrackingOptions Opts) override {
2017 PathSensitiveBugReport &Report = getParentTracker().getReport();
2018
2019 // We only track expressions if we believe that they are important. Chances
2020 // are good that control dependencies to the tracking point are also
2021 // important because of this, let's explain why we believe control reached
2022 // this point.
2023 // TODO: Shouldn't we track control dependencies of every bug location,
2024 // rather than only tracked expressions?
2025 if (LVNode->getState()
2026 ->getAnalysisManager()
2027 .getAnalyzerOptions()
2028 .ShouldTrackConditions) {
2029 Report.addVisitor<TrackControlDependencyCondBRVisitor>(
2030 &getParentTracker(), InputNode);
2031 return {/*FoundSomethingToTrack=*/true};
2032 }
2033
2034 return {};
2035 }
2036 };
2037
2038 class NilReceiverHandler final : public ExpressionHandler {
2039 public:
2040 using ExpressionHandler::ExpressionHandler;
2041
handle(const Expr * Inner,const ExplodedNode * InputNode,const ExplodedNode * LVNode,TrackingOptions Opts)2042 Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2043 const ExplodedNode *LVNode,
2044 TrackingOptions Opts) override {
2045 // The message send could be nil due to the receiver being nil.
2046 // At this point in the path, the receiver should be live since we are at
2047 // the message send expr. If it is nil, start tracking it.
2048 if (const Expr *Receiver =
2049 NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
2050 return getParentTracker().track(Receiver, LVNode, Opts);
2051
2052 return {};
2053 }
2054 };
2055
2056 class ArrayIndexHandler final : public ExpressionHandler {
2057 public:
2058 using ExpressionHandler::ExpressionHandler;
2059
handle(const Expr * Inner,const ExplodedNode * InputNode,const ExplodedNode * LVNode,TrackingOptions Opts)2060 Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2061 const ExplodedNode *LVNode,
2062 TrackingOptions Opts) override {
2063 // Track the index if this is an array subscript.
2064 if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
2065 return getParentTracker().track(
2066 Arr->getIdx(), LVNode,
2067 {Opts.Kind, /*EnableNullFPSuppression*/ false});
2068
2069 return {};
2070 }
2071 };
2072
2073 // TODO: extract it into more handlers
2074 class InterestingLValueHandler final : public ExpressionHandler {
2075 public:
2076 using ExpressionHandler::ExpressionHandler;
2077
handle(const Expr * Inner,const ExplodedNode * InputNode,const ExplodedNode * LVNode,TrackingOptions Opts)2078 Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2079 const ExplodedNode *LVNode,
2080 TrackingOptions Opts) override {
2081 ProgramStateRef LVState = LVNode->getState();
2082 const StackFrameContext *SFC = LVNode->getStackFrame();
2083 PathSensitiveBugReport &Report = getParentTracker().getReport();
2084 Tracker::Result Result;
2085
2086 // See if the expression we're interested refers to a variable.
2087 // If so, we can track both its contents and constraints on its value.
2088 if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
2089 SVal LVal = LVNode->getSVal(Inner);
2090
2091 const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
2092 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
2093
2094 // If this is a C++ reference to a null pointer, we are tracking the
2095 // pointer. In addition, we should find the store at which the reference
2096 // got initialized.
2097 if (RR && !LVIsNull)
2098 Result.combineWith(getParentTracker().track(LVal, RR, Opts, SFC));
2099
2100 // In case of C++ references, we want to differentiate between a null
2101 // reference and reference to null pointer.
2102 // If the LVal is null, check if we are dealing with null reference.
2103 // For those, we want to track the location of the reference.
2104 const MemRegion *R =
2105 (RR && LVIsNull) ? RR : LVNode->getSVal(Inner).getAsRegion();
2106
2107 if (R) {
2108
2109 // Mark both the variable region and its contents as interesting.
2110 SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
2111 Report.addVisitor<NoStoreFuncVisitor>(cast<SubRegion>(R), Opts.Kind);
2112
2113 // When we got here, we do have something to track, and we will
2114 // interrupt.
2115 Result.FoundSomethingToTrack = true;
2116 Result.WasInterrupted = true;
2117
2118 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
2119 LVNode, R, Opts.EnableNullFPSuppression, Report, V);
2120
2121 Report.markInteresting(V, Opts.Kind);
2122 Report.addVisitor<UndefOrNullArgVisitor>(R);
2123
2124 // If the contents are symbolic and null, find out when they became
2125 // null.
2126 if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
2127 if (LVState->isNull(V).isConstrainedTrue())
2128 Report.addVisitor<TrackConstraintBRVisitor>(V.castAs<DefinedSVal>(),
2129 false);
2130
2131 // Add visitor, which will suppress inline defensive checks.
2132 if (auto DV = V.getAs<DefinedSVal>())
2133 if (!DV->isZeroConstant() && Opts.EnableNullFPSuppression)
2134 // Note that LVNode may be too late (i.e., too far from the
2135 // InputNode) because the lvalue may have been computed before the
2136 // inlined call was evaluated. InputNode may as well be too early
2137 // here, because the symbol is already dead; this, however, is fine
2138 // because we can still find the node in which it collapsed to null
2139 // previously.
2140 Report.addVisitor<SuppressInlineDefensiveChecksVisitor>(*DV,
2141 InputNode);
2142 getParentTracker().track(V, R, Opts, SFC);
2143 }
2144 }
2145
2146 return Result;
2147 }
2148 };
2149
2150 /// Adds a ReturnVisitor if the given statement represents a call that was
2151 /// inlined.
2152 ///
2153 /// This will search back through the ExplodedGraph, starting from the given
2154 /// node, looking for when the given statement was processed. If it turns out
2155 /// the statement is a call that was inlined, we add the visitor to the
2156 /// bug report, so it can print a note later.
2157 class InlinedFunctionCallHandler final : public ExpressionHandler {
2158 using ExpressionHandler::ExpressionHandler;
2159
handle(const Expr * E,const ExplodedNode * InputNode,const ExplodedNode * ExprNode,TrackingOptions Opts)2160 Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2161 const ExplodedNode *ExprNode,
2162 TrackingOptions Opts) override {
2163 if (!CallEvent::isCallStmt(E))
2164 return {};
2165
2166 // First, find when we processed the statement.
2167 // If we work with a 'CXXNewExpr' that is going to be purged away before
2168 // its call take place. We would catch that purge in the last condition
2169 // as a 'StmtPoint' so we have to bypass it.
2170 const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
2171
2172 // This is moving forward when we enter into another context.
2173 const StackFrameContext *CurrentSFC = ExprNode->getStackFrame();
2174
2175 do {
2176 // If that is satisfied we found our statement as an inlined call.
2177 if (Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>())
2178 if (CEE->getCalleeContext()->getCallSite() == E)
2179 break;
2180
2181 // Try to move forward to the end of the call-chain.
2182 ExprNode = ExprNode->getFirstPred();
2183 if (!ExprNode)
2184 break;
2185
2186 const StackFrameContext *PredSFC = ExprNode->getStackFrame();
2187
2188 // If that is satisfied we found our statement.
2189 // FIXME: This code currently bypasses the call site for the
2190 // conservatively evaluated allocator.
2191 if (!BypassCXXNewExprEval)
2192 if (Optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
2193 // See if we do not enter into another context.
2194 if (SP->getStmt() == E && CurrentSFC == PredSFC)
2195 break;
2196
2197 CurrentSFC = PredSFC;
2198 } while (ExprNode->getStackFrame() == CurrentSFC);
2199
2200 // Next, step over any post-statement checks.
2201 while (ExprNode && ExprNode->getLocation().getAs<PostStmt>())
2202 ExprNode = ExprNode->getFirstPred();
2203 if (!ExprNode)
2204 return {};
2205
2206 // Finally, see if we inlined the call.
2207 Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>();
2208 if (!CEE)
2209 return {};
2210
2211 const StackFrameContext *CalleeContext = CEE->getCalleeContext();
2212 if (CalleeContext->getCallSite() != E)
2213 return {};
2214
2215 // Check the return value.
2216 ProgramStateRef State = ExprNode->getState();
2217 SVal RetVal = ExprNode->getSVal(E);
2218
2219 // Handle cases where a reference is returned and then immediately used.
2220 if (cast<Expr>(E)->isGLValue())
2221 if (Optional<Loc> LValue = RetVal.getAs<Loc>())
2222 RetVal = State->getSVal(*LValue);
2223
2224 // See if the return value is NULL. If so, suppress the report.
2225 AnalyzerOptions &Options = State->getAnalysisManager().options;
2226
2227 bool EnableNullFPSuppression = false;
2228 if (Opts.EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths)
2229 if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
2230 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
2231
2232 PathSensitiveBugReport &Report = getParentTracker().getReport();
2233 Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
2234 EnableNullFPSuppression, Options,
2235 Opts.Kind);
2236 return {true};
2237 }
2238 };
2239
2240 class DefaultExpressionHandler final : public ExpressionHandler {
2241 public:
2242 using ExpressionHandler::ExpressionHandler;
2243
handle(const Expr * Inner,const ExplodedNode * InputNode,const ExplodedNode * LVNode,TrackingOptions Opts)2244 Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
2245 const ExplodedNode *LVNode,
2246 TrackingOptions Opts) override {
2247 ProgramStateRef LVState = LVNode->getState();
2248 const StackFrameContext *SFC = LVNode->getStackFrame();
2249 PathSensitiveBugReport &Report = getParentTracker().getReport();
2250 Tracker::Result Result;
2251
2252 // If the expression is not an "lvalue expression", we can still
2253 // track the constraints on its contents.
2254 SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
2255
2256 // Is it a symbolic value?
2257 if (auto L = V.getAs<loc::MemRegionVal>()) {
2258 // FIXME: this is a hack for fixing a later crash when attempting to
2259 // dereference a void* pointer.
2260 // We should not try to dereference pointers at all when we don't care
2261 // what is written inside the pointer.
2262 bool CanDereference = true;
2263 if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
2264 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
2265 CanDereference = false;
2266 } else if (L->getRegionAs<AllocaRegion>())
2267 CanDereference = false;
2268
2269 // At this point we are dealing with the region's LValue.
2270 // However, if the rvalue is a symbolic region, we should track it as
2271 // well. Try to use the correct type when looking up the value.
2272 SVal RVal;
2273 if (ExplodedGraph::isInterestingLValueExpr(Inner))
2274 RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
2275 else if (CanDereference)
2276 RVal = LVState->getSVal(L->getRegion());
2277
2278 if (CanDereference) {
2279 Report.addVisitor<UndefOrNullArgVisitor>(L->getRegion());
2280 Result.FoundSomethingToTrack = true;
2281
2282 if (auto KV = RVal.getAs<KnownSVal>())
2283 Result.combineWith(
2284 getParentTracker().track(*KV, L->getRegion(), Opts, SFC));
2285 }
2286
2287 const MemRegion *RegionRVal = RVal.getAsRegion();
2288 if (isa_and_nonnull<SymbolicRegion>(RegionRVal)) {
2289 Report.markInteresting(RegionRVal, Opts.Kind);
2290 Report.addVisitor<TrackConstraintBRVisitor>(
2291 loc::MemRegionVal(RegionRVal),
2292 /*assumption=*/false);
2293 Result.FoundSomethingToTrack = true;
2294 }
2295 }
2296
2297 return Result;
2298 }
2299 };
2300
2301 /// Attempts to add visitors to track an RValue expression back to its point of
2302 /// origin.
2303 class PRValueHandler final : public ExpressionHandler {
2304 public:
2305 using ExpressionHandler::ExpressionHandler;
2306
handle(const Expr * E,const ExplodedNode * InputNode,const ExplodedNode * ExprNode,TrackingOptions Opts)2307 Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
2308 const ExplodedNode *ExprNode,
2309 TrackingOptions Opts) override {
2310 if (!E->isPRValue())
2311 return {};
2312
2313 const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
2314 if (!RVNode)
2315 return {};
2316
2317 ProgramStateRef RVState = RVNode->getState();
2318 SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
2319 const auto *BO = dyn_cast<BinaryOperator>(E);
2320
2321 if (!BO || !BO->isMultiplicativeOp() || !V.isZeroConstant())
2322 return {};
2323
2324 SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
2325 SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
2326
2327 // Track both LHS and RHS of a multiplication.
2328 Tracker::Result CombinedResult;
2329 Tracker &Parent = getParentTracker();
2330
2331 const auto track = [&CombinedResult, &Parent, ExprNode, Opts](Expr *Inner) {
2332 CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
2333 };
2334
2335 if (BO->getOpcode() == BO_Mul) {
2336 if (LHSV.isZeroConstant())
2337 track(BO->getLHS());
2338 if (RHSV.isZeroConstant())
2339 track(BO->getRHS());
2340 } else { // Track only the LHS of a division or a modulo.
2341 if (LHSV.isZeroConstant())
2342 track(BO->getLHS());
2343 }
2344
2345 return CombinedResult;
2346 }
2347 };
2348
Tracker(PathSensitiveBugReport & Report)2349 Tracker::Tracker(PathSensitiveBugReport &Report) : Report(Report) {
2350 // Default expression handlers.
2351 addLowPriorityHandler<ControlDependencyHandler>();
2352 addLowPriorityHandler<NilReceiverHandler>();
2353 addLowPriorityHandler<ArrayIndexHandler>();
2354 addLowPriorityHandler<InterestingLValueHandler>();
2355 addLowPriorityHandler<InlinedFunctionCallHandler>();
2356 addLowPriorityHandler<DefaultExpressionHandler>();
2357 addLowPriorityHandler<PRValueHandler>();
2358 // Default store handlers.
2359 addHighPriorityHandler<DefaultStoreHandler>();
2360 }
2361
track(const Expr * E,const ExplodedNode * N,TrackingOptions Opts)2362 Tracker::Result Tracker::track(const Expr *E, const ExplodedNode *N,
2363 TrackingOptions Opts) {
2364 if (!E || !N)
2365 return {};
2366
2367 const Expr *Inner = peelOffOuterExpr(E, N);
2368 const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
2369 if (!LVNode)
2370 return {};
2371
2372 Result CombinedResult;
2373 // Iterate through the handlers in the order according to their priorities.
2374 for (ExpressionHandlerPtr &Handler : ExpressionHandlers) {
2375 CombinedResult.combineWith(Handler->handle(Inner, N, LVNode, Opts));
2376 if (CombinedResult.WasInterrupted) {
2377 // There is no need to confuse our users here.
2378 // We got interrupted, but our users don't need to know about it.
2379 CombinedResult.WasInterrupted = false;
2380 break;
2381 }
2382 }
2383
2384 return CombinedResult;
2385 }
2386
track(SVal V,const MemRegion * R,TrackingOptions Opts,const StackFrameContext * Origin)2387 Tracker::Result Tracker::track(SVal V, const MemRegion *R, TrackingOptions Opts,
2388 const StackFrameContext *Origin) {
2389 if (auto KV = V.getAs<KnownSVal>()) {
2390 Report.addVisitor<StoreSiteFinder>(this, *KV, R, Opts, Origin);
2391 return {true};
2392 }
2393 return {};
2394 }
2395
handle(StoreInfo SI,BugReporterContext & BRC,TrackingOptions Opts)2396 PathDiagnosticPieceRef Tracker::handle(StoreInfo SI, BugReporterContext &BRC,
2397 TrackingOptions Opts) {
2398 // Iterate through the handlers in the order according to their priorities.
2399 for (StoreHandlerPtr &Handler : StoreHandlers) {
2400 if (PathDiagnosticPieceRef Result = Handler->handle(SI, BRC, Opts))
2401 // If the handler produced a non-null piece, return it.
2402 // There is no need in asking other handlers.
2403 return Result;
2404 }
2405 return {};
2406 }
2407
trackExpressionValue(const ExplodedNode * InputNode,const Expr * E,PathSensitiveBugReport & Report,TrackingOptions Opts)2408 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
2409 const Expr *E,
2410
2411 PathSensitiveBugReport &Report,
2412 TrackingOptions Opts) {
2413 return Tracker::create(Report)
2414 ->track(E, InputNode, Opts)
2415 .FoundSomethingToTrack;
2416 }
2417
trackStoredValue(KnownSVal V,const MemRegion * R,PathSensitiveBugReport & Report,TrackingOptions Opts,const StackFrameContext * Origin)2418 void bugreporter::trackStoredValue(KnownSVal V, const MemRegion *R,
2419 PathSensitiveBugReport &Report,
2420 TrackingOptions Opts,
2421 const StackFrameContext *Origin) {
2422 Tracker::create(Report)->track(V, R, Opts, Origin);
2423 }
2424
2425 //===----------------------------------------------------------------------===//
2426 // Implementation of NulReceiverBRVisitor.
2427 //===----------------------------------------------------------------------===//
2428
getNilReceiver(const Stmt * S,const ExplodedNode * N)2429 const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
2430 const ExplodedNode *N) {
2431 const auto *ME = dyn_cast<ObjCMessageExpr>(S);
2432 if (!ME)
2433 return nullptr;
2434 if (const Expr *Receiver = ME->getInstanceReceiver()) {
2435 ProgramStateRef state = N->getState();
2436 SVal V = N->getSVal(Receiver);
2437 if (state->isNull(V).isConstrainedTrue())
2438 return Receiver;
2439 }
2440 return nullptr;
2441 }
2442
2443 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)2444 NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
2445 PathSensitiveBugReport &BR) {
2446 Optional<PreStmt> P = N->getLocationAs<PreStmt>();
2447 if (!P)
2448 return nullptr;
2449
2450 const Stmt *S = P->getStmt();
2451 const Expr *Receiver = getNilReceiver(S, N);
2452 if (!Receiver)
2453 return nullptr;
2454
2455 llvm::SmallString<256> Buf;
2456 llvm::raw_svector_ostream OS(Buf);
2457
2458 if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
2459 OS << "'";
2460 ME->getSelector().print(OS);
2461 OS << "' not called";
2462 }
2463 else {
2464 OS << "No method is called";
2465 }
2466 OS << " because the receiver is nil";
2467
2468 // The receiver was nil, and hence the method was skipped.
2469 // Register a BugReporterVisitor to issue a message telling us how
2470 // the receiver was null.
2471 bugreporter::trackExpressionValue(N, Receiver, BR,
2472 {bugreporter::TrackingKind::Thorough,
2473 /*EnableNullFPSuppression*/ false});
2474 // Issue a message saying that the method was skipped.
2475 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2476 N->getLocationContext());
2477 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2478 }
2479
2480 //===----------------------------------------------------------------------===//
2481 // Visitor that tries to report interesting diagnostics from conditions.
2482 //===----------------------------------------------------------------------===//
2483
2484 /// Return the tag associated with this visitor. This tag will be used
2485 /// to make all PathDiagnosticPieces created by this visitor.
getTag()2486 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
2487
2488 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)2489 ConditionBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
2490 PathSensitiveBugReport &BR) {
2491 auto piece = VisitNodeImpl(N, BRC, BR);
2492 if (piece) {
2493 piece->setTag(getTag());
2494 if (auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2495 ev->setPrunable(true, /* override */ false);
2496 }
2497 return piece;
2498 }
2499
2500 PathDiagnosticPieceRef
VisitNodeImpl(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)2501 ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
2502 BugReporterContext &BRC,
2503 PathSensitiveBugReport &BR) {
2504 ProgramPoint ProgPoint = N->getLocation();
2505 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2506 ExprEngine::geteagerlyAssumeBinOpBifurcationTags();
2507
2508 // If an assumption was made on a branch, it should be caught
2509 // here by looking at the state transition.
2510 if (Optional<BlockEdge> BE = ProgPoint.getAs<BlockEdge>()) {
2511 const CFGBlock *SrcBlock = BE->getSrc();
2512 if (const Stmt *Term = SrcBlock->getTerminatorStmt()) {
2513 // If the tag of the previous node is 'Eagerly Assume...' the current
2514 // 'BlockEdge' has the same constraint information. We do not want to
2515 // report the value as it is just an assumption on the predecessor node
2516 // which will be caught in the next VisitNode() iteration as a 'PostStmt'.
2517 const ProgramPointTag *PreviousNodeTag =
2518 N->getFirstPred()->getLocation().getTag();
2519 if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2520 return nullptr;
2521
2522 return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2523 }
2524 return nullptr;
2525 }
2526
2527 if (Optional<PostStmt> PS = ProgPoint.getAs<PostStmt>()) {
2528 const ProgramPointTag *CurrentNodeTag = PS->getTag();
2529 if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2530 return nullptr;
2531
2532 bool TookTrue = CurrentNodeTag == Tags.first;
2533 return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2534 }
2535
2536 return nullptr;
2537 }
2538
VisitTerminator(const Stmt * Term,const ExplodedNode * N,const CFGBlock * srcBlk,const CFGBlock * dstBlk,PathSensitiveBugReport & R,BugReporterContext & BRC)2539 PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator(
2540 const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
2541 const CFGBlock *dstBlk, PathSensitiveBugReport &R,
2542 BugReporterContext &BRC) {
2543 const Expr *Cond = nullptr;
2544
2545 // In the code below, Term is a CFG terminator and Cond is a branch condition
2546 // expression upon which the decision is made on this terminator.
2547 //
2548 // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
2549 // and "x == 0" is the respective condition.
2550 //
2551 // Another example: in "if (x && y)", we've got two terminators and two
2552 // conditions due to short-circuit nature of operator "&&":
2553 // 1. The "if (x && y)" statement is a terminator,
2554 // and "y" is the respective condition.
2555 // 2. Also "x && ..." is another terminator,
2556 // and "x" is its condition.
2557
2558 switch (Term->getStmtClass()) {
2559 // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
2560 // more tricky because there are more than two branches to account for.
2561 default:
2562 return nullptr;
2563 case Stmt::IfStmtClass:
2564 Cond = cast<IfStmt>(Term)->getCond();
2565 break;
2566 case Stmt::ConditionalOperatorClass:
2567 Cond = cast<ConditionalOperator>(Term)->getCond();
2568 break;
2569 case Stmt::BinaryOperatorClass:
2570 // When we encounter a logical operator (&& or ||) as a CFG terminator,
2571 // then the condition is actually its LHS; otherwise, we'd encounter
2572 // the parent, such as if-statement, as a terminator.
2573 const auto *BO = cast<BinaryOperator>(Term);
2574 assert(BO->isLogicalOp() &&
2575 "CFG terminator is not a short-circuit operator!");
2576 Cond = BO->getLHS();
2577 break;
2578 }
2579
2580 Cond = Cond->IgnoreParens();
2581
2582 // However, when we encounter a logical operator as a branch condition,
2583 // then the condition is actually its RHS, because LHS would be
2584 // the condition for the logical operator terminator.
2585 while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2586 if (!InnerBO->isLogicalOp())
2587 break;
2588 Cond = InnerBO->getRHS()->IgnoreParens();
2589 }
2590
2591 assert(Cond);
2592 assert(srcBlk->succ_size() == 2);
2593 const bool TookTrue = *(srcBlk->succ_begin()) == dstBlk;
2594 return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2595 }
2596
2597 PathDiagnosticPieceRef
VisitTrueTest(const Expr * Cond,BugReporterContext & BRC,PathSensitiveBugReport & R,const ExplodedNode * N,bool TookTrue)2598 ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
2599 PathSensitiveBugReport &R,
2600 const ExplodedNode *N, bool TookTrue) {
2601 ProgramStateRef CurrentState = N->getState();
2602 ProgramStateRef PrevState = N->getFirstPred()->getState();
2603 const LocationContext *LCtx = N->getLocationContext();
2604
2605 // If the constraint information is changed between the current and the
2606 // previous program state we assuming the newly seen constraint information.
2607 // If we cannot evaluate the condition (and the constraints are the same)
2608 // the analyzer has no information about the value and just assuming it.
2609 bool IsAssuming =
2610 !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2611 CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2612
2613 // These will be modified in code below, but we need to preserve the original
2614 // values in case we want to throw the generic message.
2615 const Expr *CondTmp = Cond;
2616 bool TookTrueTmp = TookTrue;
2617
2618 while (true) {
2619 CondTmp = CondTmp->IgnoreParenCasts();
2620 switch (CondTmp->getStmtClass()) {
2621 default:
2622 break;
2623 case Stmt::BinaryOperatorClass:
2624 if (auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2625 BRC, R, N, TookTrueTmp, IsAssuming))
2626 return P;
2627 break;
2628 case Stmt::DeclRefExprClass:
2629 if (auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2630 BRC, R, N, TookTrueTmp, IsAssuming))
2631 return P;
2632 break;
2633 case Stmt::MemberExprClass:
2634 if (auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2635 BRC, R, N, TookTrueTmp, IsAssuming))
2636 return P;
2637 break;
2638 case Stmt::UnaryOperatorClass: {
2639 const auto *UO = cast<UnaryOperator>(CondTmp);
2640 if (UO->getOpcode() == UO_LNot) {
2641 TookTrueTmp = !TookTrueTmp;
2642 CondTmp = UO->getSubExpr();
2643 continue;
2644 }
2645 break;
2646 }
2647 }
2648 break;
2649 }
2650
2651 // Condition too complex to explain? Just say something so that the user
2652 // knew we've made some path decision at this point.
2653 // If it is too complex and we know the evaluation of the condition do not
2654 // repeat the note from 'BugReporter.cpp'
2655 if (!IsAssuming)
2656 return nullptr;
2657
2658 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2659 if (!Loc.isValid() || !Loc.asLocation().isValid())
2660 return nullptr;
2661
2662 return std::make_shared<PathDiagnosticEventPiece>(
2663 Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2664 }
2665
patternMatch(const Expr * Ex,const Expr * ParentEx,raw_ostream & Out,BugReporterContext & BRC,PathSensitiveBugReport & report,const ExplodedNode * N,Optional<bool> & prunable,bool IsSameFieldName)2666 bool ConditionBRVisitor::patternMatch(const Expr *Ex,
2667 const Expr *ParentEx,
2668 raw_ostream &Out,
2669 BugReporterContext &BRC,
2670 PathSensitiveBugReport &report,
2671 const ExplodedNode *N,
2672 Optional<bool> &prunable,
2673 bool IsSameFieldName) {
2674 const Expr *OriginalExpr = Ex;
2675 Ex = Ex->IgnoreParenCasts();
2676
2677 if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2678 isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2679 isa<FloatingLiteral>(Ex)) {
2680 // Use heuristics to determine if the expression is a macro
2681 // expanding to a literal and if so, use the macro's name.
2682 SourceLocation BeginLoc = OriginalExpr->getBeginLoc();
2683 SourceLocation EndLoc = OriginalExpr->getEndLoc();
2684 if (BeginLoc.isMacroID() && EndLoc.isMacroID()) {
2685 const SourceManager &SM = BRC.getSourceManager();
2686 const LangOptions &LO = BRC.getASTContext().getLangOpts();
2687 if (Lexer::isAtStartOfMacroExpansion(BeginLoc, SM, LO) &&
2688 Lexer::isAtEndOfMacroExpansion(EndLoc, SM, LO)) {
2689 CharSourceRange R = Lexer::getAsCharRange({BeginLoc, EndLoc}, SM, LO);
2690 Out << Lexer::getSourceText(R, SM, LO);
2691 return false;
2692 }
2693 }
2694 }
2695
2696 if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2697 const bool quotes = isa<VarDecl>(DR->getDecl());
2698 if (quotes) {
2699 Out << '\'';
2700 const LocationContext *LCtx = N->getLocationContext();
2701 const ProgramState *state = N->getState().get();
2702 if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2703 LCtx).getAsRegion()) {
2704 if (report.isInteresting(R))
2705 prunable = false;
2706 else {
2707 const ProgramState *state = N->getState().get();
2708 SVal V = state->getSVal(R);
2709 if (report.isInteresting(V))
2710 prunable = false;
2711 }
2712 }
2713 }
2714 Out << DR->getDecl()->getDeclName().getAsString();
2715 if (quotes)
2716 Out << '\'';
2717 return quotes;
2718 }
2719
2720 if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2721 QualType OriginalTy = OriginalExpr->getType();
2722 if (OriginalTy->isPointerType()) {
2723 if (IL->getValue() == 0) {
2724 Out << "null";
2725 return false;
2726 }
2727 }
2728 else if (OriginalTy->isObjCObjectPointerType()) {
2729 if (IL->getValue() == 0) {
2730 Out << "nil";
2731 return false;
2732 }
2733 }
2734
2735 Out << IL->getValue();
2736 return false;
2737 }
2738
2739 if (const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2740 if (!IsSameFieldName)
2741 Out << "field '" << ME->getMemberDecl()->getName() << '\'';
2742 else
2743 Out << '\''
2744 << Lexer::getSourceText(
2745 CharSourceRange::getTokenRange(Ex->getSourceRange()),
2746 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2747 << '\'';
2748 }
2749
2750 return false;
2751 }
2752
VisitTrueTest(const Expr * Cond,const BinaryOperator * BExpr,BugReporterContext & BRC,PathSensitiveBugReport & R,const ExplodedNode * N,bool TookTrue,bool IsAssuming)2753 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
2754 const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC,
2755 PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue,
2756 bool IsAssuming) {
2757 bool shouldInvert = false;
2758 Optional<bool> shouldPrune;
2759
2760 // Check if the field name of the MemberExprs is ambiguous. Example:
2761 // " 'a.d' is equal to 'h.d' " in 'test/Analysis/null-deref-path-notes.cpp'.
2762 bool IsSameFieldName = false;
2763 const auto *LhsME = dyn_cast<MemberExpr>(BExpr->getLHS()->IgnoreParenCasts());
2764 const auto *RhsME = dyn_cast<MemberExpr>(BExpr->getRHS()->IgnoreParenCasts());
2765
2766 if (LhsME && RhsME)
2767 IsSameFieldName =
2768 LhsME->getMemberDecl()->getName() == RhsME->getMemberDecl()->getName();
2769
2770 SmallString<128> LhsString, RhsString;
2771 {
2772 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2773 const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS, BRC, R,
2774 N, shouldPrune, IsSameFieldName);
2775 const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS, BRC, R,
2776 N, shouldPrune, IsSameFieldName);
2777
2778 shouldInvert = !isVarLHS && isVarRHS;
2779 }
2780
2781 BinaryOperator::Opcode Op = BExpr->getOpcode();
2782
2783 if (BinaryOperator::isAssignmentOp(Op)) {
2784 // For assignment operators, all that we care about is that the LHS
2785 // evaluates to "true" or "false".
2786 return VisitConditionVariable(LhsString, BExpr->getLHS(), BRC, R, N,
2787 TookTrue);
2788 }
2789
2790 // For non-assignment operations, we require that we can understand
2791 // both the LHS and RHS.
2792 if (LhsString.empty() || RhsString.empty() ||
2793 !BinaryOperator::isComparisonOp(Op) || Op == BO_Cmp)
2794 return nullptr;
2795
2796 // Should we invert the strings if the LHS is not a variable name?
2797 SmallString<256> buf;
2798 llvm::raw_svector_ostream Out(buf);
2799 Out << (IsAssuming ? "Assuming " : "")
2800 << (shouldInvert ? RhsString : LhsString) << " is ";
2801
2802 // Do we need to invert the opcode?
2803 if (shouldInvert)
2804 switch (Op) {
2805 default: break;
2806 case BO_LT: Op = BO_GT; break;
2807 case BO_GT: Op = BO_LT; break;
2808 case BO_LE: Op = BO_GE; break;
2809 case BO_GE: Op = BO_LE; break;
2810 }
2811
2812 if (!TookTrue)
2813 switch (Op) {
2814 case BO_EQ: Op = BO_NE; break;
2815 case BO_NE: Op = BO_EQ; break;
2816 case BO_LT: Op = BO_GE; break;
2817 case BO_GT: Op = BO_LE; break;
2818 case BO_LE: Op = BO_GT; break;
2819 case BO_GE: Op = BO_LT; break;
2820 default:
2821 return nullptr;
2822 }
2823
2824 switch (Op) {
2825 case BO_EQ:
2826 Out << "equal to ";
2827 break;
2828 case BO_NE:
2829 Out << "not equal to ";
2830 break;
2831 default:
2832 Out << BinaryOperator::getOpcodeStr(Op) << ' ';
2833 break;
2834 }
2835
2836 Out << (shouldInvert ? LhsString : RhsString);
2837 const LocationContext *LCtx = N->getLocationContext();
2838 const SourceManager &SM = BRC.getSourceManager();
2839
2840 if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) ||
2841 isVarAnInterestingCondition(BExpr->getRHS(), N, &R))
2842 Out << WillBeUsedForACondition;
2843
2844 // Convert 'field ...' to 'Field ...' if it is a MemberExpr.
2845 std::string Message = std::string(Out.str());
2846 Message[0] = toupper(Message[0]);
2847
2848 // If we know the value create a pop-up note to the value part of 'BExpr'.
2849 if (!IsAssuming) {
2850 PathDiagnosticLocation Loc;
2851 if (!shouldInvert) {
2852 if (LhsME && LhsME->getMemberLoc().isValid())
2853 Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM);
2854 else
2855 Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx);
2856 } else {
2857 if (RhsME && RhsME->getMemberLoc().isValid())
2858 Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM);
2859 else
2860 Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx);
2861 }
2862
2863 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2864 }
2865
2866 PathDiagnosticLocation Loc(Cond, SM, LCtx);
2867 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2868 if (shouldPrune.hasValue())
2869 event->setPrunable(shouldPrune.getValue());
2870 return event;
2871 }
2872
VisitConditionVariable(StringRef LhsString,const Expr * CondVarExpr,BugReporterContext & BRC,PathSensitiveBugReport & report,const ExplodedNode * N,bool TookTrue)2873 PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable(
2874 StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC,
2875 PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) {
2876 // FIXME: If there's already a constraint tracker for this variable,
2877 // we shouldn't emit anything here (c.f. the double note in
2878 // test/Analysis/inlining/path-notes.c)
2879 SmallString<256> buf;
2880 llvm::raw_svector_ostream Out(buf);
2881 Out << "Assuming " << LhsString << " is ";
2882
2883 if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true))
2884 return nullptr;
2885
2886 const LocationContext *LCtx = N->getLocationContext();
2887 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2888
2889 if (isVarAnInterestingCondition(CondVarExpr, N, &report))
2890 Out << WillBeUsedForACondition;
2891
2892 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2893
2894 if (isInterestingExpr(CondVarExpr, N, &report))
2895 event->setPrunable(false);
2896
2897 return event;
2898 }
2899
VisitTrueTest(const Expr * Cond,const DeclRefExpr * DRE,BugReporterContext & BRC,PathSensitiveBugReport & report,const ExplodedNode * N,bool TookTrue,bool IsAssuming)2900 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
2901 const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC,
2902 PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
2903 bool IsAssuming) {
2904 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2905 if (!VD)
2906 return nullptr;
2907
2908 SmallString<256> Buf;
2909 llvm::raw_svector_ostream Out(Buf);
2910
2911 Out << (IsAssuming ? "Assuming '" : "'") << VD->getDeclName() << "' is ";
2912
2913 if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2914 return nullptr;
2915
2916 const LocationContext *LCtx = N->getLocationContext();
2917
2918 if (isVarAnInterestingCondition(DRE, N, &report))
2919 Out << WillBeUsedForACondition;
2920
2921 // If we know the value create a pop-up note to the 'DRE'.
2922 if (!IsAssuming) {
2923 PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
2924 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2925 }
2926
2927 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2928 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2929
2930 if (isInterestingExpr(DRE, N, &report))
2931 event->setPrunable(false);
2932
2933 return std::move(event);
2934 }
2935
VisitTrueTest(const Expr * Cond,const MemberExpr * ME,BugReporterContext & BRC,PathSensitiveBugReport & report,const ExplodedNode * N,bool TookTrue,bool IsAssuming)2936 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
2937 const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
2938 PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
2939 bool IsAssuming) {
2940 SmallString<256> Buf;
2941 llvm::raw_svector_ostream Out(Buf);
2942
2943 Out << (IsAssuming ? "Assuming field '" : "Field '")
2944 << ME->getMemberDecl()->getName() << "' is ";
2945
2946 if (!printValue(ME, Out, N, TookTrue, IsAssuming))
2947 return nullptr;
2948
2949 const LocationContext *LCtx = N->getLocationContext();
2950 PathDiagnosticLocation Loc;
2951
2952 // If we know the value create a pop-up note to the member of the MemberExpr.
2953 if (!IsAssuming && ME->getMemberLoc().isValid())
2954 Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager());
2955 else
2956 Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
2957
2958 if (!Loc.isValid() || !Loc.asLocation().isValid())
2959 return nullptr;
2960
2961 if (isVarAnInterestingCondition(ME, N, &report))
2962 Out << WillBeUsedForACondition;
2963
2964 // If we know the value create a pop-up note.
2965 if (!IsAssuming)
2966 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2967
2968 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2969 if (isInterestingExpr(ME, N, &report))
2970 event->setPrunable(false);
2971 return event;
2972 }
2973
printValue(const Expr * CondVarExpr,raw_ostream & Out,const ExplodedNode * N,bool TookTrue,bool IsAssuming)2974 bool ConditionBRVisitor::printValue(const Expr *CondVarExpr, raw_ostream &Out,
2975 const ExplodedNode *N, bool TookTrue,
2976 bool IsAssuming) {
2977 QualType Ty = CondVarExpr->getType();
2978
2979 if (Ty->isPointerType()) {
2980 Out << (TookTrue ? "non-null" : "null");
2981 return true;
2982 }
2983
2984 if (Ty->isObjCObjectPointerType()) {
2985 Out << (TookTrue ? "non-nil" : "nil");
2986 return true;
2987 }
2988
2989 if (!Ty->isIntegralOrEnumerationType())
2990 return false;
2991
2992 Optional<const llvm::APSInt *> IntValue;
2993 if (!IsAssuming)
2994 IntValue = getConcreteIntegerValue(CondVarExpr, N);
2995
2996 if (IsAssuming || !IntValue.hasValue()) {
2997 if (Ty->isBooleanType())
2998 Out << (TookTrue ? "true" : "false");
2999 else
3000 Out << (TookTrue ? "not equal to 0" : "0");
3001 } else {
3002 if (Ty->isBooleanType())
3003 Out << (IntValue.getValue()->getBoolValue() ? "true" : "false");
3004 else
3005 Out << *IntValue.getValue();
3006 }
3007
3008 return true;
3009 }
3010
3011 constexpr llvm::StringLiteral ConditionBRVisitor::GenericTrueMessage;
3012 constexpr llvm::StringLiteral ConditionBRVisitor::GenericFalseMessage;
3013
isPieceMessageGeneric(const PathDiagnosticPiece * Piece)3014 bool ConditionBRVisitor::isPieceMessageGeneric(
3015 const PathDiagnosticPiece *Piece) {
3016 return Piece->getString() == GenericTrueMessage ||
3017 Piece->getString() == GenericFalseMessage;
3018 }
3019
3020 //===----------------------------------------------------------------------===//
3021 // Implementation of LikelyFalsePositiveSuppressionBRVisitor.
3022 //===----------------------------------------------------------------------===//
3023
finalizeVisitor(BugReporterContext & BRC,const ExplodedNode * N,PathSensitiveBugReport & BR)3024 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
3025 BugReporterContext &BRC, const ExplodedNode *N,
3026 PathSensitiveBugReport &BR) {
3027 // Here we suppress false positives coming from system headers. This list is
3028 // based on known issues.
3029 const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
3030 const Decl *D = N->getLocationContext()->getDecl();
3031
3032 if (AnalysisDeclContext::isInStdNamespace(D)) {
3033 // Skip reports within the 'std' namespace. Although these can sometimes be
3034 // the user's fault, we currently don't report them very well, and
3035 // Note that this will not help for any other data structure libraries, like
3036 // TR1, Boost, or llvm/ADT.
3037 if (Options.ShouldSuppressFromCXXStandardLibrary) {
3038 BR.markInvalid(getTag(), nullptr);
3039 return;
3040 } else {
3041 // If the complete 'std' suppression is not enabled, suppress reports
3042 // from the 'std' namespace that are known to produce false positives.
3043
3044 // The analyzer issues a false use-after-free when std::list::pop_front
3045 // or std::list::pop_back are called multiple times because we cannot
3046 // reason about the internal invariants of the data structure.
3047 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3048 const CXXRecordDecl *CD = MD->getParent();
3049 if (CD->getName() == "list") {
3050 BR.markInvalid(getTag(), nullptr);
3051 return;
3052 }
3053 }
3054
3055 // The analyzer issues a false positive when the constructor of
3056 // std::__independent_bits_engine from algorithms is used.
3057 if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
3058 const CXXRecordDecl *CD = MD->getParent();
3059 if (CD->getName() == "__independent_bits_engine") {
3060 BR.markInvalid(getTag(), nullptr);
3061 return;
3062 }
3063 }
3064
3065 for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
3066 LCtx = LCtx->getParent()) {
3067 const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
3068 if (!MD)
3069 continue;
3070
3071 const CXXRecordDecl *CD = MD->getParent();
3072 // The analyzer issues a false positive on
3073 // std::basic_string<uint8_t> v; v.push_back(1);
3074 // and
3075 // std::u16string s; s += u'a';
3076 // because we cannot reason about the internal invariants of the
3077 // data structure.
3078 if (CD->getName() == "basic_string") {
3079 BR.markInvalid(getTag(), nullptr);
3080 return;
3081 }
3082
3083 // The analyzer issues a false positive on
3084 // std::shared_ptr<int> p(new int(1)); p = nullptr;
3085 // because it does not reason properly about temporary destructors.
3086 if (CD->getName() == "shared_ptr") {
3087 BR.markInvalid(getTag(), nullptr);
3088 return;
3089 }
3090 }
3091 }
3092 }
3093
3094 // Skip reports within the sys/queue.h macros as we do not have the ability to
3095 // reason about data structure shapes.
3096 const SourceManager &SM = BRC.getSourceManager();
3097 FullSourceLoc Loc = BR.getLocation().asLocation();
3098 while (Loc.isMacroID()) {
3099 Loc = Loc.getSpellingLoc();
3100 if (SM.getFilename(Loc).endswith("sys/queue.h")) {
3101 BR.markInvalid(getTag(), nullptr);
3102 return;
3103 }
3104 }
3105 }
3106
3107 //===----------------------------------------------------------------------===//
3108 // Implementation of UndefOrNullArgVisitor.
3109 //===----------------------------------------------------------------------===//
3110
3111 PathDiagnosticPieceRef
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)3112 UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
3113 PathSensitiveBugReport &BR) {
3114 ProgramStateRef State = N->getState();
3115 ProgramPoint ProgLoc = N->getLocation();
3116
3117 // We are only interested in visiting CallEnter nodes.
3118 Optional<CallEnter> CEnter = ProgLoc.getAs<CallEnter>();
3119 if (!CEnter)
3120 return nullptr;
3121
3122 // Check if one of the arguments is the region the visitor is tracking.
3123 CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
3124 CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
3125 unsigned Idx = 0;
3126 ArrayRef<ParmVarDecl *> parms = Call->parameters();
3127
3128 for (const auto ParamDecl : parms) {
3129 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
3130 ++Idx;
3131
3132 // Are we tracking the argument or its subregion?
3133 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
3134 continue;
3135
3136 // Check the function parameter type.
3137 assert(ParamDecl && "Formal parameter has no decl?");
3138 QualType T = ParamDecl->getType();
3139
3140 if (!(T->isAnyPointerType() || T->isReferenceType())) {
3141 // Function can only change the value passed in by address.
3142 continue;
3143 }
3144
3145 // If it is a const pointer value, the function does not intend to
3146 // change the value.
3147 if (T->getPointeeType().isConstQualified())
3148 continue;
3149
3150 // Mark the call site (LocationContext) as interesting if the value of the
3151 // argument is undefined or '0'/'NULL'.
3152 SVal BoundVal = State->getSVal(R);
3153 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
3154 BR.markInteresting(CEnter->getCalleeContext());
3155 return nullptr;
3156 }
3157 }
3158 return nullptr;
3159 }
3160
3161 //===----------------------------------------------------------------------===//
3162 // Implementation of FalsePositiveRefutationBRVisitor.
3163 //===----------------------------------------------------------------------===//
3164
FalsePositiveRefutationBRVisitor()3165 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
3166 : Constraints(ConstraintMap::Factory().getEmptyMap()) {}
3167
finalizeVisitor(BugReporterContext & BRC,const ExplodedNode * EndPathNode,PathSensitiveBugReport & BR)3168 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
3169 BugReporterContext &BRC, const ExplodedNode *EndPathNode,
3170 PathSensitiveBugReport &BR) {
3171 // Collect new constraints
3172 addConstraints(EndPathNode, /*OverwriteConstraintsOnExistingSyms=*/true);
3173
3174 // Create a refutation manager
3175 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
3176 ASTContext &Ctx = BRC.getASTContext();
3177
3178 // Add constraints to the solver
3179 for (const auto &I : Constraints) {
3180 const SymbolRef Sym = I.first;
3181 auto RangeIt = I.second.begin();
3182
3183 llvm::SMTExprRef SMTConstraints = SMTConv::getRangeExpr(
3184 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
3185 /*InRange=*/true);
3186 while ((++RangeIt) != I.second.end()) {
3187 SMTConstraints = RefutationSolver->mkOr(
3188 SMTConstraints, SMTConv::getRangeExpr(RefutationSolver, Ctx, Sym,
3189 RangeIt->From(), RangeIt->To(),
3190 /*InRange=*/true));
3191 }
3192
3193 RefutationSolver->addConstraint(SMTConstraints);
3194 }
3195
3196 // And check for satisfiability
3197 Optional<bool> IsSAT = RefutationSolver->check();
3198 if (!IsSAT.hasValue())
3199 return;
3200
3201 if (!IsSAT.getValue())
3202 BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
3203 }
3204
addConstraints(const ExplodedNode * N,bool OverwriteConstraintsOnExistingSyms)3205 void FalsePositiveRefutationBRVisitor::addConstraints(
3206 const ExplodedNode *N, bool OverwriteConstraintsOnExistingSyms) {
3207 // Collect new constraints
3208 ConstraintMap NewCs = getConstraintMap(N->getState());
3209 ConstraintMap::Factory &CF = N->getState()->get_context<ConstraintMap>();
3210
3211 // Add constraints if we don't have them yet
3212 for (auto const &C : NewCs) {
3213 const SymbolRef &Sym = C.first;
3214 if (!Constraints.contains(Sym)) {
3215 // This symbol is new, just add the constraint.
3216 Constraints = CF.add(Constraints, Sym, C.second);
3217 } else if (OverwriteConstraintsOnExistingSyms) {
3218 // Overwrite the associated constraint of the Symbol.
3219 Constraints = CF.remove(Constraints, Sym);
3220 Constraints = CF.add(Constraints, Sym, C.second);
3221 }
3222 }
3223 }
3224
VisitNode(const ExplodedNode * N,BugReporterContext &,PathSensitiveBugReport &)3225 PathDiagnosticPieceRef FalsePositiveRefutationBRVisitor::VisitNode(
3226 const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) {
3227 addConstraints(N, /*OverwriteConstraintsOnExistingSyms=*/false);
3228 return nullptr;
3229 }
3230
Profile(llvm::FoldingSetNodeID & ID) const3231 void FalsePositiveRefutationBRVisitor::Profile(
3232 llvm::FoldingSetNodeID &ID) const {
3233 static int Tag = 0;
3234 ID.AddPointer(&Tag);
3235 }
3236
3237 //===----------------------------------------------------------------------===//
3238 // Implementation of TagVisitor.
3239 //===----------------------------------------------------------------------===//
3240
3241 int NoteTag::Kind = 0;
3242
Profile(llvm::FoldingSetNodeID & ID) const3243 void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
3244 static int Tag = 0;
3245 ID.AddPointer(&Tag);
3246 }
3247
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & R)3248 PathDiagnosticPieceRef TagVisitor::VisitNode(const ExplodedNode *N,
3249 BugReporterContext &BRC,
3250 PathSensitiveBugReport &R) {
3251 ProgramPoint PP = N->getLocation();
3252 const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag());
3253 if (!T)
3254 return nullptr;
3255
3256 if (Optional<std::string> Msg = T->generateMessage(BRC, R)) {
3257 PathDiagnosticLocation Loc =
3258 PathDiagnosticLocation::create(PP, BRC.getSourceManager());
3259 auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
3260 Piece->setPrunable(T->isPrunable());
3261 return Piece;
3262 }
3263
3264 return nullptr;
3265 }
3266