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

source code of clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp