clang 17.0.0git
NullabilityChecker.cpp
Go to the documentation of this file.
1//===-- NullabilityChecker.cpp - Nullability checker ----------------------===//
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 checker tries to find nullability violations. There are several kinds of
10// possible violations:
11// * Null pointer is passed to a pointer which has a _Nonnull type.
12// * Null pointer is returned from a function which has a _Nonnull return type.
13// * Nullable pointer is passed to a pointer which has a _Nonnull type.
14// * Nullable pointer is returned from a function which has a _Nonnull return
15// type.
16// * Nullable pointer is dereferenced.
17//
18// This checker propagates the nullability information of the pointers and looks
19// for the patterns that are described above. Explicit casts are trusted and are
20// considered a way to suppress false positives for this checker. The other way
21// to suppress warnings would be to add asserts or guarding if statements to the
22// code. In addition to the nullability propagation this checker also uses some
23// heuristics to suppress potential false positives.
24//
25//===----------------------------------------------------------------------===//
26
28
35
36#include "llvm/ADT/StringExtras.h"
37#include "llvm/Support/Path.h"
38
39using namespace clang;
40using namespace ento;
41
42namespace {
43
44/// Returns the most nullable nullability. This is used for message expressions
45/// like [receiver method], where the nullability of this expression is either
46/// the nullability of the receiver or the nullability of the return type of the
47/// method, depending on which is more nullable. Contradicted is considered to
48/// be the most nullable, to avoid false positive results.
49Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
50 return static_cast<Nullability>(
51 std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
52}
53
54const char *getNullabilityString(Nullability Nullab) {
55 switch (Nullab) {
56 case Nullability::Contradicted:
57 return "contradicted";
58 case Nullability::Nullable:
59 return "nullable";
60 case Nullability::Unspecified:
61 return "unspecified";
62 case Nullability::Nonnull:
63 return "nonnull";
64 }
65 llvm_unreachable("Unexpected enumeration.");
66 return "";
67}
68
69// These enums are used as an index to ErrorMessages array.
70enum class ErrorKind : int {
71 NilAssignedToNonnull,
72 NilPassedToNonnull,
73 NilReturnedToNonnull,
74 NullableAssignedToNonnull,
75 NullableReturnedToNonnull,
76 NullableDereferenced,
77 NullablePassedToNonnull
78};
79
80class NullabilityChecker
81 : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
82 check::PostCall, check::PostStmt<ExplicitCastExpr>,
83 check::PostObjCMessage, check::DeadSymbols, eval::Assume,
84 check::Location, check::Event<ImplicitNullDerefEvent>> {
85
86public:
87 // If true, the checker will not diagnose nullabilility issues for calls
88 // to system headers. This option is motivated by the observation that large
89 // projects may have many nullability warnings. These projects may
90 // find warnings about nullability annotations that they have explicitly
91 // added themselves higher priority to fix than warnings on calls to system
92 // libraries.
93 bool NoDiagnoseCallsToSystemHeaders = false;
94
95 void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
96 void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
97 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
98 void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
99 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
100 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
101 void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
102 void checkEvent(ImplicitNullDerefEvent Event) const;
103 void checkLocation(SVal Location, bool IsLoad, const Stmt *S,
104 CheckerContext &C) const;
105 ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
106 bool Assumption) const;
107
108 void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
109 const char *Sep) const override;
110
111 enum CheckKind {
112 CK_NullPassedToNonnull,
113 CK_NullReturnedFromNonnull,
114 CK_NullableDereferenced,
115 CK_NullablePassedToNonnull,
116 CK_NullableReturnedFromNonnull,
117 CK_NumCheckKinds
118 };
119
120 bool ChecksEnabled[CK_NumCheckKinds] = {false};
121 CheckerNameRef CheckNames[CK_NumCheckKinds];
122 mutable std::unique_ptr<BugType> BTs[CK_NumCheckKinds];
123
124 const std::unique_ptr<BugType> &getBugType(CheckKind Kind) const {
125 if (!BTs[Kind])
126 BTs[Kind].reset(new BugType(CheckNames[Kind], "Nullability",
128 return BTs[Kind];
129 }
130
131 // When set to false no nullability information will be tracked in
132 // NullabilityMap. It is possible to catch errors like passing a null pointer
133 // to a callee that expects nonnull argument without the information that is
134 // stored in the NullabilityMap. This is an optimization.
135 bool NeedTracking = false;
136
137private:
138 class NullabilityBugVisitor : public BugReporterVisitor {
139 public:
140 NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
141
142 void Profile(llvm::FoldingSetNodeID &ID) const override {
143 static int X = 0;
144 ID.AddPointer(&X);
145 ID.AddPointer(Region);
146 }
147
148 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
150 PathSensitiveBugReport &BR) override;
151
152 private:
153 // The tracked region.
154 const MemRegion *Region;
155 };
156
157 /// When any of the nonnull arguments of the analyzed function is null, do not
158 /// report anything and turn off the check.
159 ///
160 /// When \p SuppressPath is set to true, no more bugs will be reported on this
161 /// path by this checker.
162 void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error, CheckKind CK,
163 ExplodedNode *N, const MemRegion *Region,
165 const Stmt *ValueExpr = nullptr,
166 bool SuppressPath = false) const;
167
168 void reportBug(StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
169 const MemRegion *Region, BugReporter &BR,
170 const Stmt *ValueExpr = nullptr) const {
171 const std::unique_ptr<BugType> &BT = getBugType(CK);
172 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
173 if (Region) {
174 R->markInteresting(Region);
175 R->addVisitor<NullabilityBugVisitor>(Region);
176 }
177 if (ValueExpr) {
178 R->addRange(ValueExpr->getSourceRange());
179 if (Error == ErrorKind::NilAssignedToNonnull ||
180 Error == ErrorKind::NilPassedToNonnull ||
181 Error == ErrorKind::NilReturnedToNonnull)
182 if (const auto *Ex = dyn_cast<Expr>(ValueExpr))
184 }
185 BR.emitReport(std::move(R));
186 }
187
188 /// If an SVal wraps a region that should be tracked, it will return a pointer
189 /// to the wrapped region. Otherwise it will return a nullptr.
190 const SymbolicRegion *getTrackRegion(SVal Val,
191 bool CheckSuperRegion = false) const;
192
193 /// Returns true if the call is diagnosable in the current analyzer
194 /// configuration.
195 bool isDiagnosableCall(const CallEvent &Call) const {
196 if (NoDiagnoseCallsToSystemHeaders && Call.isInSystemHeader())
197 return false;
198
199 return true;
200 }
201};
202
203class NullabilityState {
204public:
205 NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
206 : Nullab(Nullab), Source(Source) {}
207
208 const Stmt *getNullabilitySource() const { return Source; }
209
210 Nullability getValue() const { return Nullab; }
211
212 void Profile(llvm::FoldingSetNodeID &ID) const {
213 ID.AddInteger(static_cast<char>(Nullab));
214 ID.AddPointer(Source);
215 }
216
217 void print(raw_ostream &Out) const {
218 Out << getNullabilityString(Nullab) << "\n";
219 }
220
221private:
222 Nullability Nullab;
223 // Source is the expression which determined the nullability. For example in a
224 // message like [nullable nonnull_returning] has nullable nullability, because
225 // the receiver is nullable. Here the receiver will be the source of the
226 // nullability. This is useful information when the diagnostics are generated.
227 const Stmt *Source;
228};
229
230bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
231 return Lhs.getValue() == Rhs.getValue() &&
232 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
233}
234
235// For the purpose of tracking historical property accesses, the key for lookup
236// is an object pointer (could be an instance or a class) paired with the unique
237// identifier for the property being invoked on that object.
238using ObjectPropPair = std::pair<const MemRegion *, const IdentifierInfo *>;
239
240// Metadata associated with the return value from a recorded property access.
241struct ConstrainedPropertyVal {
242 // This will reference the conjured return SVal for some call
243 // of the form [object property]
245
246 // If the SVal has been determined to be nonnull, that is recorded here
247 bool isConstrainedNonnull;
248
249 ConstrainedPropertyVal(DefinedOrUnknownSVal SV)
250 : Value(SV), isConstrainedNonnull(false) {}
251
252 void Profile(llvm::FoldingSetNodeID &ID) const {
253 Value.Profile(ID);
254 ID.AddInteger(isConstrainedNonnull ? 1 : 0);
255 }
256};
257
258bool operator==(const ConstrainedPropertyVal &Lhs,
259 const ConstrainedPropertyVal &Rhs) {
260 return Lhs.Value == Rhs.Value &&
261 Lhs.isConstrainedNonnull == Rhs.isConstrainedNonnull;
262}
263
264} // end anonymous namespace
265
267 NullabilityState)
269 ConstrainedPropertyVal)
270
271// We say "the nullability type invariant is violated" when a location with a
272// non-null type contains NULL or a function with a non-null return type returns
273// NULL. Violations of the nullability type invariant can be detected either
274// directly (for example, when NULL is passed as an argument to a nonnull
275// parameter) or indirectly (for example, when, inside a function, the
276// programmer defensively checks whether a nonnull parameter contains NULL and
277// finds that it does).
278//
279// As a matter of policy, the nullability checker typically warns on direct
280// violations of the nullability invariant (although it uses various
281// heuristics to suppress warnings in some cases) but will not warn if the
282// invariant has already been violated along the path (either directly or
283// indirectly). As a practical matter, this prevents the analyzer from
284// (1) warning on defensive code paths where a nullability precondition is
285// determined to have been violated, (2) warning additional times after an
286// initial direct violation has been discovered, and (3) warning after a direct
287// violation that has been implicitly or explicitly suppressed (for
288// example, with a cast of NULL to _Nonnull). In essence, once an invariant
289// violation is detected on a path, this checker will be essentially turned off
290// for the rest of the analysis
291//
292// The analyzer takes this approach (rather than generating a sink node) to
293// ensure coverage of defensive paths, which may be important for backwards
294// compatibility in codebases that were developed without nullability in mind.
295REGISTER_TRAIT_WITH_PROGRAMSTATE(InvariantViolated, bool)
296
298
300 ProgramStateRef State) {
301 ConditionTruthVal Nullness = State->isNull(Val);
302 if (Nullness.isConstrainedFalse())
304 if (Nullness.isConstrainedTrue())
307}
308
309const SymbolicRegion *
310NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
311 if (!NeedTracking)
312 return nullptr;
313
314 auto RegionSVal = Val.getAs<loc::MemRegionVal>();
315 if (!RegionSVal)
316 return nullptr;
317
318 const MemRegion *Region = RegionSVal->getRegion();
319
320 if (CheckSuperRegion) {
321 if (const SubRegion *FieldReg = Region->getAs<FieldRegion>()) {
322 if (const auto *ER = dyn_cast<ElementRegion>(FieldReg->getSuperRegion()))
323 FieldReg = ER;
324 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
325 }
326 if (auto ElementReg = Region->getAs<ElementRegion>())
327 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
328 }
329
330 return dyn_cast<SymbolicRegion>(Region);
331}
332
333PathDiagnosticPieceRef NullabilityChecker::NullabilityBugVisitor::VisitNode(
334 const ExplodedNode *N, BugReporterContext &BRC,
336 ProgramStateRef State = N->getState();
337 ProgramStateRef StatePrev = N->getFirstPred()->getState();
338
339 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
340 const NullabilityState *TrackedNullabPrev =
341 StatePrev->get<NullabilityMap>(Region);
342 if (!TrackedNullab)
343 return nullptr;
344
345 if (TrackedNullabPrev &&
346 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
347 return nullptr;
348
349 // Retrieve the associated statement.
350 const Stmt *S = TrackedNullab->getNullabilitySource();
351 if (!S || S->getBeginLoc().isInvalid()) {
352 S = N->getStmtForDiagnostics();
353 }
354
355 if (!S)
356 return nullptr;
357
358 std::string InfoText =
359 (llvm::Twine("Nullability '") +
360 getNullabilityString(TrackedNullab->getValue()) + "' is inferred")
361 .str();
362
363 // Generate the extra diagnostic.
365 N->getLocationContext());
366 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
367}
368
369/// Returns true when the value stored at the given location has been
370/// constrained to null after being passed through an object of nonnnull type.
372 SVal LV, QualType T) {
373 if (getNullabilityAnnotation(T) != Nullability::Nonnull)
374 return false;
375
376 auto RegionVal = LV.getAs<loc::MemRegionVal>();
377 if (!RegionVal)
378 return false;
379
380 // If the value was constrained to null *after* it was passed through that
381 // location, it could not have been a concrete pointer *when* it was passed.
382 // In that case we would have handled the situation when the value was
383 // bound to that location, by emitting (or not emitting) a report.
384 // Therefore we are only interested in symbolic regions that can be either
385 // null or non-null depending on the value of their respective symbol.
386 auto StoredVal = State->getSVal(*RegionVal).getAs<loc::MemRegionVal>();
387 if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
388 return false;
389
390 if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
391 return true;
392
393 return false;
394}
395
396static bool
398 ProgramStateRef State,
399 const LocationContext *LocCtxt) {
400 for (const auto *ParamDecl : Params) {
401 if (ParamDecl->isParameterPack())
402 break;
403
404 SVal LV = State->getLValue(ParamDecl, LocCtxt);
406 ParamDecl->getType())) {
407 return true;
408 }
409 }
410 return false;
411}
412
413static bool
415 const LocationContext *LocCtxt) {
416 auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->getDecl());
417 if (!MD || !MD->isInstanceMethod())
418 return false;
419
420 const ImplicitParamDecl *SelfDecl = LocCtxt->getSelfDecl();
421 if (!SelfDecl)
422 return false;
423
424 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
425
426 const ObjCObjectPointerType *SelfType =
427 dyn_cast<ObjCObjectPointerType>(SelfDecl->getType());
428 if (!SelfType)
429 return false;
430
431 const ObjCInterfaceDecl *ID = SelfType->getInterfaceDecl();
432 if (!ID)
433 return false;
434
435 for (const auto *IvarDecl : ID->ivars()) {
436 SVal LV = State->getLValue(IvarDecl, SelfVal);
437 if (checkValueAtLValForInvariantViolation(State, LV, IvarDecl->getType())) {
438 return true;
439 }
440 }
441 return false;
442}
443
445 CheckerContext &C) {
446 if (State->get<InvariantViolated>())
447 return true;
448
449 const LocationContext *LocCtxt = C.getLocationContext();
450 const Decl *D = LocCtxt->getDecl();
451 if (!D)
452 return false;
453
455 if (const auto *BD = dyn_cast<BlockDecl>(D))
456 Params = BD->parameters();
457 else if (const auto *FD = dyn_cast<FunctionDecl>(D))
458 Params = FD->parameters();
459 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
460 Params = MD->parameters();
461 else
462 return false;
463
464 if (checkParamsForPreconditionViolation(Params, State, LocCtxt) ||
465 checkSelfIvarsForInvariantViolation(State, LocCtxt)) {
466 if (!N->isSink())
467 C.addTransition(State->set<InvariantViolated>(true), N);
468 return true;
469 }
470 return false;
471}
472
473void NullabilityChecker::reportBugIfInvariantHolds(
474 StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
475 const MemRegion *Region, CheckerContext &C, const Stmt *ValueExpr,
476 bool SuppressPath) const {
477 ProgramStateRef OriginalState = N->getState();
478
479 if (checkInvariantViolation(OriginalState, N, C))
480 return;
481 if (SuppressPath) {
482 OriginalState = OriginalState->set<InvariantViolated>(true);
483 N = C.addTransition(OriginalState, N);
484 }
485
486 reportBug(Msg, Error, CK, N, Region, C.getBugReporter(), ValueExpr);
487}
488
489/// Cleaning up the program state.
490void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
491 CheckerContext &C) const {
492 ProgramStateRef State = C.getState();
493 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
494 for (NullabilityMapTy::iterator I = Nullabilities.begin(),
495 E = Nullabilities.end();
496 I != E; ++I) {
497 const auto *Region = I->first->getAs<SymbolicRegion>();
498 assert(Region && "Non-symbolic region is tracked.");
499 if (SR.isDead(Region->getSymbol())) {
500 State = State->remove<NullabilityMap>(I->first);
501 }
502 }
503
504 // When an object goes out of scope, we can free the history associated
505 // with any property accesses on that object
506 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
507 for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
508 E = PropertyAccesses.end();
509 I != E; ++I) {
510 const MemRegion *ReceiverRegion = I->first.first;
511 if (!SR.isLiveRegion(ReceiverRegion)) {
512 State = State->remove<PropertyAccessesMap>(I->first);
513 }
514 }
515
516 // When one of the nonnull arguments are constrained to be null, nullability
517 // preconditions are violated. It is not enough to check this only when we
518 // actually report an error, because at that time interesting symbols might be
519 // reaped.
520 if (checkInvariantViolation(State, C.getPredecessor(), C))
521 return;
522 C.addTransition(State);
523}
524
525/// This callback triggers when a pointer is dereferenced and the analyzer does
526/// not know anything about the value of that pointer. When that pointer is
527/// nullable, this code emits a warning.
528void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
529 if (Event.SinkNode->getState()->get<InvariantViolated>())
530 return;
531
532 const MemRegion *Region =
533 getTrackRegion(Event.Location, /*CheckSuperRegion=*/true);
534 if (!Region)
535 return;
536
537 ProgramStateRef State = Event.SinkNode->getState();
538 const NullabilityState *TrackedNullability =
539 State->get<NullabilityMap>(Region);
540
541 if (!TrackedNullability)
542 return;
543
544 if (ChecksEnabled[CK_NullableDereferenced] &&
545 TrackedNullability->getValue() == Nullability::Nullable) {
546 BugReporter &BR = *Event.BR;
547 // Do not suppress errors on defensive code paths, because dereferencing
548 // a nullable pointer is always an error.
549 if (Event.IsDirectDereference)
550 reportBug("Nullable pointer is dereferenced",
551 ErrorKind::NullableDereferenced, CK_NullableDereferenced,
552 Event.SinkNode, Region, BR);
553 else {
554 reportBug("Nullable pointer is passed to a callee that requires a "
555 "non-null",
556 ErrorKind::NullablePassedToNonnull, CK_NullableDereferenced,
557 Event.SinkNode, Region, BR);
558 }
559 }
560}
561
562// Whenever we see a load from a typed memory region that's been annotated as
563// 'nonnull', we want to trust the user on that and assume that it is is indeed
564// non-null.
565//
566// We do so even if the value is known to have been assigned to null.
567// The user should be warned on assigning the null value to a non-null pointer
568// as opposed to warning on the later dereference of this pointer.
569//
570// \code
571// int * _Nonnull var = 0; // we want to warn the user here...
572// // . . .
573// *var = 42; // ...and not here
574// \endcode
575void NullabilityChecker::checkLocation(SVal Location, bool IsLoad,
576 const Stmt *S,
577 CheckerContext &Context) const {
578 // We should care only about loads.
579 // The main idea is to add a constraint whenever we're loading a value from
580 // an annotated pointer type.
581 if (!IsLoad)
582 return;
583
584 // Annotations that we want to consider make sense only for types.
585 const auto *Region =
586 dyn_cast_or_null<TypedValueRegion>(Location.getAsRegion());
587 if (!Region)
588 return;
589
590 ProgramStateRef State = Context.getState();
591
592 auto StoredVal = State->getSVal(Region).getAs<loc::MemRegionVal>();
593 if (!StoredVal)
594 return;
595
596 Nullability NullabilityOfTheLoadedValue =
597 getNullabilityAnnotation(Region->getValueType());
598
599 if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
600 // It doesn't matter what we think about this particular pointer, it should
601 // be considered non-null as annotated by the developer.
602 if (ProgramStateRef NewState = State->assume(*StoredVal, true)) {
603 Context.addTransition(NewState);
604 }
605 }
606}
607
608/// Find the outermost subexpression of E that is not an implicit cast.
609/// This looks through the implicit casts to _Nonnull that ARC adds to
610/// return expressions of ObjC types when the return type of the function or
611/// method is non-null but the express is not.
612static const Expr *lookThroughImplicitCasts(const Expr *E) {
613 return E->IgnoreImpCasts();
614}
615
616/// This method check when nullable pointer or null value is returned from a
617/// function that has nonnull return type.
618void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
619 CheckerContext &C) const {
620 auto RetExpr = S->getRetValue();
621 if (!RetExpr)
622 return;
623
624 if (!RetExpr->getType()->isAnyPointerType())
625 return;
626
627 ProgramStateRef State = C.getState();
628 if (State->get<InvariantViolated>())
629 return;
630
631 auto RetSVal = C.getSVal(S).getAs<DefinedOrUnknownSVal>();
632 if (!RetSVal)
633 return;
634
635 bool InSuppressedMethodFamily = false;
636
637 QualType RequiredRetType;
638 AnalysisDeclContext *DeclCtxt =
639 C.getLocationContext()->getAnalysisDeclContext();
640 const Decl *D = DeclCtxt->getDecl();
641 if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
642 // HACK: This is a big hammer to avoid warning when there are defensive
643 // nil checks in -init and -copy methods. We should add more sophisticated
644 // logic here to suppress on common defensive idioms but still
645 // warn when there is a likely problem.
646 ObjCMethodFamily Family = MD->getMethodFamily();
647 if (OMF_init == Family || OMF_copy == Family || OMF_mutableCopy == Family)
648 InSuppressedMethodFamily = true;
649
650 RequiredRetType = MD->getReturnType();
651 } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
652 RequiredRetType = FD->getReturnType();
653 } else {
654 return;
655 }
656
657 NullConstraint Nullness = getNullConstraint(*RetSVal, State);
658
659 Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
660
661 // If the returned value is null but the type of the expression
662 // generating it is nonnull then we will suppress the diagnostic.
663 // This enables explicit suppression when returning a nil literal in a
664 // function with a _Nonnull return type:
665 // return (NSString * _Nonnull)0;
666 Nullability RetExprTypeLevelNullability =
668
669 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
670 Nullness == NullConstraint::IsNull);
671 if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
672 RetExprTypeLevelNullability != Nullability::Nonnull &&
673 !InSuppressedMethodFamily && C.getLocationContext()->inTopFrame()) {
674 static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
675 ExplodedNode *N = C.generateErrorNode(State, &Tag);
676 if (!N)
677 return;
678
679 SmallString<256> SBuf;
680 llvm::raw_svector_ostream OS(SBuf);
681 OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
682 OS << " returned from a " << C.getDeclDescription(D) <<
683 " that is expected to return a non-null value";
684 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
685 CK_NullReturnedFromNonnull, N, nullptr, C,
686 RetExpr);
687 return;
688 }
689
690 // If null was returned from a non-null function, mark the nullability
691 // invariant as violated even if the diagnostic was suppressed.
692 if (NullReturnedFromNonNull) {
693 State = State->set<InvariantViolated>(true);
694 C.addTransition(State);
695 return;
696 }
697
698 const MemRegion *Region = getTrackRegion(*RetSVal);
699 if (!Region)
700 return;
701
702 const NullabilityState *TrackedNullability =
703 State->get<NullabilityMap>(Region);
704 if (TrackedNullability) {
705 Nullability TrackedNullabValue = TrackedNullability->getValue();
706 if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
707 Nullness != NullConstraint::IsNotNull &&
708 TrackedNullabValue == Nullability::Nullable &&
709 RequiredNullability == Nullability::Nonnull) {
710 static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
711 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
712
713 SmallString<256> SBuf;
714 llvm::raw_svector_ostream OS(SBuf);
715 OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
716 " that is expected to return a non-null value";
717
718 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
719 CK_NullableReturnedFromNonnull, N, Region, C);
720 }
721 return;
722 }
723 if (RequiredNullability == Nullability::Nullable) {
724 State = State->set<NullabilityMap>(Region,
725 NullabilityState(RequiredNullability,
726 S));
727 C.addTransition(State);
728 }
729}
730
731/// This callback warns when a nullable pointer or a null value is passed to a
732/// function that expects its argument to be nonnull.
733void NullabilityChecker::checkPreCall(const CallEvent &Call,
734 CheckerContext &C) const {
735 if (!Call.getDecl())
736 return;
737
738 ProgramStateRef State = C.getState();
739 if (State->get<InvariantViolated>())
740 return;
741
742 ProgramStateRef OrigState = State;
743
744 unsigned Idx = 0;
745 for (const ParmVarDecl *Param : Call.parameters()) {
746 if (Param->isParameterPack())
747 break;
748
749 if (Idx >= Call.getNumArgs())
750 break;
751
752 const Expr *ArgExpr = Call.getArgExpr(Idx);
753 auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
754 if (!ArgSVal)
755 continue;
756
757 if (!Param->getType()->isAnyPointerType() &&
758 !Param->getType()->isReferenceType())
759 continue;
760
761 NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
762
763 Nullability RequiredNullability =
764 getNullabilityAnnotation(Param->getType());
765 Nullability ArgExprTypeLevelNullability =
767
768 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
769
770 if (ChecksEnabled[CK_NullPassedToNonnull] &&
771 Nullness == NullConstraint::IsNull &&
772 ArgExprTypeLevelNullability != Nullability::Nonnull &&
773 RequiredNullability == Nullability::Nonnull &&
774 isDiagnosableCall(Call)) {
775 ExplodedNode *N = C.generateErrorNode(State);
776 if (!N)
777 return;
778
779 SmallString<256> SBuf;
780 llvm::raw_svector_ostream OS(SBuf);
781 OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
782 OS << " passed to a callee that requires a non-null " << ParamIdx
783 << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
784 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
785 CK_NullPassedToNonnull, N, nullptr, C, ArgExpr,
786 /*SuppressPath=*/false);
787 return;
788 }
789
790 const MemRegion *Region = getTrackRegion(*ArgSVal);
791 if (!Region)
792 continue;
793
794 const NullabilityState *TrackedNullability =
795 State->get<NullabilityMap>(Region);
796
797 if (TrackedNullability) {
798 if (Nullness == NullConstraint::IsNotNull ||
799 TrackedNullability->getValue() != Nullability::Nullable)
800 continue;
801
802 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
803 RequiredNullability == Nullability::Nonnull &&
804 isDiagnosableCall(Call)) {
805 ExplodedNode *N = C.addTransition(State);
806 SmallString<256> SBuf;
807 llvm::raw_svector_ostream OS(SBuf);
808 OS << "Nullable pointer is passed to a callee that requires a non-null "
809 << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
810 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
811 CK_NullablePassedToNonnull, N, Region, C,
812 ArgExpr, /*SuppressPath=*/true);
813 return;
814 }
815 if (ChecksEnabled[CK_NullableDereferenced] &&
816 Param->getType()->isReferenceType()) {
817 ExplodedNode *N = C.addTransition(State);
818 reportBugIfInvariantHolds("Nullable pointer is dereferenced",
819 ErrorKind::NullableDereferenced,
820 CK_NullableDereferenced, N, Region, C,
821 ArgExpr, /*SuppressPath=*/true);
822 return;
823 }
824 continue;
825 }
826 }
827 if (State != OrigState)
828 C.addTransition(State);
829}
830
831/// Suppress the nullability warnings for some functions.
832void NullabilityChecker::checkPostCall(const CallEvent &Call,
833 CheckerContext &C) const {
834 auto Decl = Call.getDecl();
835 if (!Decl)
836 return;
837 // ObjC Messages handles in a different callback.
838 if (Call.getKind() == CE_ObjCMessage)
839 return;
840 const FunctionType *FuncType = Decl->getFunctionType();
841 if (!FuncType)
842 return;
843 QualType ReturnType = FuncType->getReturnType();
844 if (!ReturnType->isAnyPointerType())
845 return;
846 ProgramStateRef State = C.getState();
847 if (State->get<InvariantViolated>())
848 return;
849
850 const MemRegion *Region = getTrackRegion(Call.getReturnValue());
851 if (!Region)
852 return;
853
854 // CG headers are misannotated. Do not warn for symbols that are the results
855 // of CG calls.
856 const SourceManager &SM = C.getSourceManager();
857 StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
858 if (llvm::sys::path::filename(FilePath).startswith("CG")) {
859 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
860 C.addTransition(State);
861 return;
862 }
863
864 const NullabilityState *TrackedNullability =
865 State->get<NullabilityMap>(Region);
866
867 if (!TrackedNullability &&
868 getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
869 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
870 C.addTransition(State);
871 }
872}
873
875 ProgramStateRef State) {
876 if (M.isReceiverSelfOrSuper()) {
877 // For super and super class receivers we assume that the receiver is
878 // nonnull.
879 return Nullability::Nonnull;
880 }
881 // Otherwise look up nullability in the state.
882 SVal Receiver = M.getReceiverSVal();
883 if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
884 // If the receiver is constrained to be nonnull, assume that it is nonnull
885 // regardless of its type.
886 NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
887 if (Nullness == NullConstraint::IsNotNull)
888 return Nullability::Nonnull;
889 }
890 auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
891 if (ValueRegionSVal) {
892 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
893 assert(SelfRegion);
894
895 const NullabilityState *TrackedSelfNullability =
896 State->get<NullabilityMap>(SelfRegion);
897 if (TrackedSelfNullability)
898 return TrackedSelfNullability->getValue();
899 }
900 return Nullability::Unspecified;
901}
902
903// The return value of a property access is typically a temporary value which
904// will not be tracked in a persistent manner by the analyzer. We use
905// evalAssume() in order to immediately record constraints on those temporaries
906// at the time they are imposed (e.g. by a nil-check conditional).
907ProgramStateRef NullabilityChecker::evalAssume(ProgramStateRef State, SVal Cond,
908 bool Assumption) const {
909 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
910 for (PropertyAccessesMapTy::iterator I = PropertyAccesses.begin(),
911 E = PropertyAccesses.end();
912 I != E; ++I) {
913 if (!I->second.isConstrainedNonnull) {
914 ConditionTruthVal IsNonNull = State->isNonNull(I->second.Value);
915 if (IsNonNull.isConstrainedTrue()) {
916 ConstrainedPropertyVal Replacement = I->second;
917 Replacement.isConstrainedNonnull = true;
918 State = State->set<PropertyAccessesMap>(I->first, Replacement);
919 } else if (IsNonNull.isConstrainedFalse()) {
920 // Space optimization: no point in tracking constrained-null cases
921 State = State->remove<PropertyAccessesMap>(I->first);
922 }
923 }
924 }
925
926 return State;
927}
928
929/// Calculate the nullability of the result of a message expr based on the
930/// nullability of the receiver, the nullability of the return value, and the
931/// constraints.
932void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
933 CheckerContext &C) const {
934 auto Decl = M.getDecl();
935 if (!Decl)
936 return;
937 QualType RetType = Decl->getReturnType();
938 if (!RetType->isAnyPointerType())
939 return;
940
941 ProgramStateRef State = C.getState();
942 if (State->get<InvariantViolated>())
943 return;
944
945 const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
946 if (!ReturnRegion)
947 return;
948
949 auto Interface = Decl->getClassInterface();
950 auto Name = Interface ? Interface->getName() : "";
951 // In order to reduce the noise in the diagnostics generated by this checker,
952 // some framework and programming style based heuristics are used. These
953 // heuristics are for Cocoa APIs which have NS prefix.
954 if (Name.startswith("NS")) {
955 // Developers rely on dynamic invariants such as an item should be available
956 // in a collection, or a collection is not empty often. Those invariants can
957 // not be inferred by any static analysis tool. To not to bother the users
958 // with too many false positives, every item retrieval function should be
959 // ignored for collections. The instance methods of dictionaries in Cocoa
960 // are either item retrieval related or not interesting nullability wise.
961 // Using this fact, to keep the code easier to read just ignore the return
962 // value of every instance method of dictionaries.
963 if (M.isInstanceMessage() && Name.contains("Dictionary")) {
964 State =
965 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
966 C.addTransition(State);
967 return;
968 }
969 // For similar reasons ignore some methods of Cocoa arrays.
970 StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
971 if (Name.contains("Array") &&
972 (FirstSelectorSlot == "firstObject" ||
973 FirstSelectorSlot == "lastObject")) {
974 State =
975 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
976 C.addTransition(State);
977 return;
978 }
979
980 // Encoding related methods of string should not fail when lossless
981 // encodings are used. Using lossless encodings is so frequent that ignoring
982 // this class of methods reduced the emitted diagnostics by about 30% on
983 // some projects (and all of that was false positives).
984 if (Name.contains("String")) {
985 for (auto *Param : M.parameters()) {
986 if (Param->getName() == "encoding") {
987 State = State->set<NullabilityMap>(ReturnRegion,
988 Nullability::Contradicted);
989 C.addTransition(State);
990 return;
991 }
992 }
993 }
994 }
995
997 Nullability SelfNullability = getReceiverNullability(M, State);
998
999 const NullabilityState *NullabilityOfReturn =
1000 State->get<NullabilityMap>(ReturnRegion);
1001
1002 if (NullabilityOfReturn) {
1003 // When we have a nullability tracked for the return value, the nullability
1004 // of the expression will be the most nullable of the receiver and the
1005 // return value.
1006 Nullability RetValTracked = NullabilityOfReturn->getValue();
1007 Nullability ComputedNullab =
1008 getMostNullable(RetValTracked, SelfNullability);
1009 if (ComputedNullab != RetValTracked &&
1010 ComputedNullab != Nullability::Unspecified) {
1011 const Stmt *NullabilitySource =
1012 ComputedNullab == RetValTracked
1013 ? NullabilityOfReturn->getNullabilitySource()
1014 : Message->getInstanceReceiver();
1015 State = State->set<NullabilityMap>(
1016 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1017 C.addTransition(State);
1018 }
1019 return;
1020 }
1021
1022 // No tracked information. Use static type information for return value.
1023 Nullability RetNullability = getNullabilityAnnotation(RetType);
1024
1025 // Properties might be computed, which means the property value could
1026 // theoretically change between calls even in commonly-observed cases like
1027 // this:
1028 //
1029 // if (foo.prop) { // ok, it's nonnull here...
1030 // [bar doStuffWithNonnullVal:foo.prop]; // ...but what about
1031 // here?
1032 // }
1033 //
1034 // If the property is nullable-annotated, a naive analysis would lead to many
1035 // false positives despite the presence of probably-correct nil-checks. To
1036 // reduce the false positive rate, we maintain a history of the most recently
1037 // observed property value. For each property access, if the prior value has
1038 // been constrained to be not nil then we will conservatively assume that the
1039 // next access can be inferred as nonnull.
1040 if (RetNullability != Nullability::Nonnull &&
1041 M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined) {
1042 bool LookupResolved = false;
1043 if (const MemRegion *ReceiverRegion = getTrackRegion(M.getReceiverSVal())) {
1045 LookupResolved = true;
1046 ObjectPropPair Key = std::make_pair(ReceiverRegion, Ident);
1047 const ConstrainedPropertyVal *PrevPropVal =
1048 State->get<PropertyAccessesMap>(Key);
1049 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1050 RetNullability = Nullability::Nonnull;
1051 } else {
1052 // If a previous property access was constrained as nonnull, we hold
1053 // on to that constraint (effectively inferring that all subsequent
1054 // accesses on that code path can be inferred as nonnull). If the
1055 // previous property access was *not* constrained as nonnull, then
1056 // let's throw it away in favor of keeping the SVal associated with
1057 // this more recent access.
1058 if (auto ReturnSVal =
1060 State = State->set<PropertyAccessesMap>(
1061 Key, ConstrainedPropertyVal(*ReturnSVal));
1062 }
1063 }
1064 }
1065 }
1066
1067 if (!LookupResolved) {
1068 // Fallback: err on the side of suppressing the false positive.
1069 RetNullability = Nullability::Nonnull;
1070 }
1071 }
1072
1073 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1074 if (ComputedNullab == Nullability::Nullable) {
1075 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1076 ? Message
1077 : Message->getInstanceReceiver();
1078 State = State->set<NullabilityMap>(
1079 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1080 C.addTransition(State);
1081 }
1082}
1083
1084/// Explicit casts are trusted. If there is a disagreement in the nullability
1085/// annotations in the destination and the source or '0' is casted to nonnull
1086/// track the value as having contraditory nullability. This will allow users to
1087/// suppress warnings.
1088void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
1089 CheckerContext &C) const {
1090 QualType OriginType = CE->getSubExpr()->getType();
1091 QualType DestType = CE->getType();
1092 if (!OriginType->isAnyPointerType())
1093 return;
1094 if (!DestType->isAnyPointerType())
1095 return;
1096
1097 ProgramStateRef State = C.getState();
1098 if (State->get<InvariantViolated>())
1099 return;
1100
1101 Nullability DestNullability = getNullabilityAnnotation(DestType);
1102
1103 // No explicit nullability in the destination type, so this cast does not
1104 // change the nullability.
1105 if (DestNullability == Nullability::Unspecified)
1106 return;
1107
1108 auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
1109 const MemRegion *Region = getTrackRegion(*RegionSVal);
1110 if (!Region)
1111 return;
1112
1113 // When 0 is converted to nonnull mark it as contradicted.
1114 if (DestNullability == Nullability::Nonnull) {
1115 NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
1116 if (Nullness == NullConstraint::IsNull) {
1117 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1118 C.addTransition(State);
1119 return;
1120 }
1121 }
1122
1123 const NullabilityState *TrackedNullability =
1124 State->get<NullabilityMap>(Region);
1125
1126 if (!TrackedNullability) {
1127 if (DestNullability != Nullability::Nullable)
1128 return;
1129 State = State->set<NullabilityMap>(Region,
1130 NullabilityState(DestNullability, CE));
1131 C.addTransition(State);
1132 return;
1133 }
1134
1135 if (TrackedNullability->getValue() != DestNullability &&
1136 TrackedNullability->getValue() != Nullability::Contradicted) {
1137 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1138 C.addTransition(State);
1139 }
1140}
1141
1142/// For a given statement performing a bind, attempt to syntactically
1143/// match the expression resulting in the bound value.
1144static const Expr * matchValueExprForBind(const Stmt *S) {
1145 // For `x = e` the value expression is the right-hand side.
1146 if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1147 if (BinOp->getOpcode() == BO_Assign)
1148 return BinOp->getRHS();
1149 }
1150
1151 // For `int x = e` the value expression is the initializer.
1152 if (auto *DS = dyn_cast<DeclStmt>(S)) {
1153 if (DS->isSingleDecl()) {
1154 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1155 if (!VD)
1156 return nullptr;
1157
1158 if (const Expr *Init = VD->getInit())
1159 return Init;
1160 }
1161 }
1162
1163 return nullptr;
1164}
1165
1166/// Returns true if \param S is a DeclStmt for a local variable that
1167/// ObjC automated reference counting initialized with zero.
1169 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1170 // prevents false positives when a _Nonnull local variable cannot be
1171 // initialized with an initialization expression:
1172 // NSString * _Nonnull s; // no-warning
1173 // @autoreleasepool {
1174 // s = ...
1175 // }
1176 //
1177 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1178 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1179 // the zero-initialized definition will unexpectedly yield nil.
1180
1181 // Locals are only zero-initialized when automated reference counting
1182 // is turned on.
1183 if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
1184 return false;
1185
1186 auto *DS = dyn_cast<DeclStmt>(S);
1187 if (!DS || !DS->isSingleDecl())
1188 return false;
1189
1190 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1191 if (!VD)
1192 return false;
1193
1194 // Sema only zero-initializes locals with ObjCLifetimes.
1195 if(!VD->getType().getQualifiers().hasObjCLifetime())
1196 return false;
1197
1198 const Expr *Init = VD->getInit();
1199 assert(Init && "ObjC local under ARC without initializer");
1200
1201 // Return false if the local is explicitly initialized (e.g., with '= nil').
1202 if (!isa<ImplicitValueInitExpr>(Init))
1203 return false;
1204
1205 return true;
1206}
1207
1208/// Propagate the nullability information through binds and warn when nullable
1209/// pointer or null symbol is assigned to a pointer with a nonnull type.
1210void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
1211 CheckerContext &C) const {
1212 const TypedValueRegion *TVR =
1213 dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
1214 if (!TVR)
1215 return;
1216
1217 QualType LocType = TVR->getValueType();
1218 if (!LocType->isAnyPointerType())
1219 return;
1220
1221 ProgramStateRef State = C.getState();
1222 if (State->get<InvariantViolated>())
1223 return;
1224
1225 auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1226 if (!ValDefOrUnknown)
1227 return;
1228
1229 NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1230
1231 Nullability ValNullability = Nullability::Unspecified;
1232 if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1233 ValNullability = getNullabilityAnnotation(Sym->getType());
1234
1235 Nullability LocNullability = getNullabilityAnnotation(LocType);
1236
1237 // If the type of the RHS expression is nonnull, don't warn. This
1238 // enables explicit suppression with a cast to nonnull.
1239 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1240 const Expr *ValueExpr = matchValueExprForBind(S);
1241 if (ValueExpr) {
1242 ValueExprTypeLevelNullability =
1244 }
1245
1246 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1247 RhsNullness == NullConstraint::IsNull);
1248 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1249 ValNullability != Nullability::Nonnull &&
1250 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1252 static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
1253 ExplodedNode *N = C.generateErrorNode(State, &Tag);
1254 if (!N)
1255 return;
1256
1257
1258 const Stmt *ValueStmt = S;
1259 if (ValueExpr)
1260 ValueStmt = ValueExpr;
1261
1262 SmallString<256> SBuf;
1263 llvm::raw_svector_ostream OS(SBuf);
1264 OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
1265 OS << " assigned to a pointer which is expected to have non-null value";
1266 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1267 CK_NullPassedToNonnull, N, nullptr, C, ValueStmt);
1268 return;
1269 }
1270
1271 // If null was returned from a non-null function, mark the nullability
1272 // invariant as violated even if the diagnostic was suppressed.
1273 if (NullAssignedToNonNull) {
1274 State = State->set<InvariantViolated>(true);
1275 C.addTransition(State);
1276 return;
1277 }
1278
1279 // Intentionally missing case: '0' is bound to a reference. It is handled by
1280 // the DereferenceChecker.
1281
1282 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1283 if (!ValueRegion)
1284 return;
1285
1286 const NullabilityState *TrackedNullability =
1287 State->get<NullabilityMap>(ValueRegion);
1288
1289 if (TrackedNullability) {
1290 if (RhsNullness == NullConstraint::IsNotNull ||
1291 TrackedNullability->getValue() != Nullability::Nullable)
1292 return;
1293 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1294 LocNullability == Nullability::Nonnull) {
1295 static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1296 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
1297 reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1298 "which is expected to have non-null value",
1299 ErrorKind::NullableAssignedToNonnull,
1300 CK_NullablePassedToNonnull, N, ValueRegion, C);
1301 }
1302 return;
1303 }
1304
1305 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1306
1307 if (ValNullability == Nullability::Nullable) {
1308 // Trust the static information of the value more than the static
1309 // information on the location.
1310 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1311 State = State->set<NullabilityMap>(
1312 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1313 C.addTransition(State);
1314 return;
1315 }
1316
1317 if (LocNullability == Nullability::Nullable) {
1318 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1319 State = State->set<NullabilityMap>(
1320 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1321 C.addTransition(State);
1322 }
1323}
1324
1325void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1326 const char *NL, const char *Sep) const {
1327
1328 NullabilityMapTy B = State->get<NullabilityMap>();
1329
1330 if (State->get<InvariantViolated>())
1331 Out << Sep << NL
1332 << "Nullability invariant was violated, warnings suppressed." << NL;
1333
1334 if (B.isEmpty())
1335 return;
1336
1337 if (!State->get<InvariantViolated>())
1338 Out << Sep << NL;
1339
1340 for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1341 Out << I->first << " : ";
1342 I->second.print(Out);
1343 Out << NL;
1344 }
1345}
1346
1347void ento::registerNullabilityBase(CheckerManager &mgr) {
1348 mgr.registerChecker<NullabilityChecker>();
1349}
1350
1351bool ento::shouldRegisterNullabilityBase(const CheckerManager &mgr) {
1352 return true;
1353}
1354
1355#define REGISTER_CHECKER(name, trackingRequired) \
1356 void ento::register##name##Checker(CheckerManager &mgr) { \
1357 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1358 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1359 checker->CheckNames[NullabilityChecker::CK_##name] = \
1360 mgr.getCurrentCheckerName(); \
1361 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1362 checker->NoDiagnoseCallsToSystemHeaders = \
1363 checker->NoDiagnoseCallsToSystemHeaders || \
1364 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1365 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1366 } \
1367 \
1368 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
1369 return true; \
1370 }
1371
1372// The checks are likely to be turned on by default and it is possible to do
1373// them without tracking any nullability related information. As an optimization
1374// no nullability information will be tracked when only these two checks are
1375// enables.
1376REGISTER_CHECKER(NullPassedToNonnull, false)
1377REGISTER_CHECKER(NullReturnedFromNonnull, false)
1378
1379REGISTER_CHECKER(NullableDereferenced, true)
1380REGISTER_CHECKER(NullablePassedToNonnull, true)
1381REGISTER_CHECKER(NullableReturnedFromNonnull, true)
#define V(N, I)
Definition: ASTContext.h:3217
static SVal getValue(SVal val, SValBuilder &svalBuilder)
#define SM(sm)
Definition: Cuda.cpp:78
llvm::Error Error
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &, QualType)
Definition: InterpFrame.cpp:89
llvm::raw_ostream & OS
Definition: Logger.cpp:24
static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val, ProgramStateRef State)
#define REGISTER_CHECKER(name, trackingRequired)
static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S)
Returns true if.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State, SVal LV, QualType T)
Returns true when the value stored at the given location has been constrained to null after being pas...
static const Expr * matchValueExprForBind(const Stmt *S)
For a given statement performing a bind, attempt to syntactically match the expression resulting in t...
static bool checkSelfIvarsForInvariantViolation(ProgramStateRef State, const LocationContext *LocCtxt)
static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N, CheckerContext &C)
static const Expr * lookThroughImplicitCasts(const Expr *E)
Find the outermost subexpression of E that is not an implicit cast.
static bool checkParamsForPreconditionViolation(ArrayRef< ParmVarDecl * > Params, ProgramStateRef State, const LocationContext *LocCtxt)
static Nullability getReceiverNullability(const ObjCMethodCall &M, ProgramStateRef State)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
Expr * getSubExpr()
Definition: Expr.h:3532
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
Definition: DeclBase.cpp:1032
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:424
ExplicitCastExpr - An explicit cast written in the source code.
Definition: Expr.h:3704
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3026
QualType getType() const
Definition: Expr.h:142
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:3694
QualType getReturnType() const
Definition: Type.h:3959
One of these records is kept for each identifier that is lexed.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
const ImplicitParamDecl * getSelfDecl() const
Represents an ObjC class declaration.
Definition: DeclObjC.h:1147
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:942
Represents a pointer to an Objective C object.
Definition: Type.h:6297
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
Definition: Type.h:6349
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Definition: Attr.h:242
Represents a parameter to a function.
Definition: Decl.h:1722
A (possibly-)qualified type.
Definition: Type.h:736
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:2806
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
Definition: Stmt.h:72
bool isObjCObjectPointerType() const
Definition: Type.h:7038
bool isAnyPointerType() const
Definition: Type.h:6914
QualType getType() const
Definition: Decl.h:712
Represents a statement that could possibly have a value and type.
Definition: Stmt.h:1824
const SourceManager & getSourceManager() const
Definition: BugReporter.h:721
BugReporterVisitors are used to add custom diagnostics along a path.
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:149
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:322
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
Definition: Checker.h:501
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:510
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
ElementRegion is used to represent both array elements and casts.
Definition: MemRegion.h:1189
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
const RegionTy * getAs() const
Definition: MemRegion.h:1337
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:1163
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Definition: CallEvent.h:1192
bool isInstanceMessage() const
Definition: CallEvent.h:1204
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:1040
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:1188
ArrayRef< ParmVarDecl * > parameters() const override
Return call's formal parameters.
Definition: CallEvent.cpp:947
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:979
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Definition: CallEvent.cpp:995
Selector getSelector() const
Definition: CallEvent.h:1212
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:72
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition: SVals.h:103
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
Definition: SVals.cpp:184
const MemRegion * getAsRegion() const
Definition: SVals.cpp:120
SubRegion - A region that subsets another larger region.
Definition: MemRegion.h:442
Symbolic value.
Definition: SymExpr.h:29
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
bool isLiveRegion(const MemRegion *region)
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:770
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:531
virtual QualType getValueType() const =0
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
Nullability getNullabilityAnnotation(QualType Type)
Get nullability annotation for a given type.
@ CE_ObjCMessage
Definition: CallEvent.h:76
@ OCM_PropertyAccess
Definition: CallEvent.h:1155
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
Definition: Interp.h:1493
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:207
ObjCMethodFamily
A family of Objective-C methods.
@ OMF_mutableCopy
@ C
Languages that the frontend can parse and compile.
#define true
Definition: stdbool.h:21
#define false
Definition: stdbool.h:22
We dereferenced a location that may be null.
Definition: Checker.h:553