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