clang 20.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 if (const auto *FunDecl = C.getLocationContext()->getDecl();
696 FunDecl && FunDecl->getAttr<ReturnsNonNullAttr>() &&
697 (RequiredNullability == Nullability::Unspecified ||
698 RequiredNullability == Nullability::Nullable)) {
699 // If a function is marked with the returns_nonnull attribute,
700 // the return value must be non-null.
701 RequiredNullability = Nullability::Nonnull;
702 }
703
704 // If the returned value is null but the type of the expression
705 // generating it is nonnull then we will suppress the diagnostic.
706 // This enables explicit suppression when returning a nil literal in a
707 // function with a _Nonnull return type:
708 // return (NSString * _Nonnull)0;
709 Nullability RetExprTypeLevelNullability =
711
712 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
713 Nullness == NullConstraint::IsNull);
714 if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
715 RetExprTypeLevelNullability != Nullability::Nonnull &&
716 !InSuppressedMethodFamily) {
717 static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
718 ExplodedNode *N = C.generateErrorNode(State, &Tag);
719 if (!N)
720 return;
721
722 SmallString<256> SBuf;
723 llvm::raw_svector_ostream OS(SBuf);
724 OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
725 OS << " returned from a " << C.getDeclDescription(D) <<
726 " that is expected to return a non-null value";
727 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
728 CK_NullReturnedFromNonnull, N, nullptr, C,
729 RetExpr);
730 return;
731 }
732
733 // If null was returned from a non-null function, mark the nullability
734 // invariant as violated even if the diagnostic was suppressed.
735 if (NullReturnedFromNonNull) {
736 State = State->set<InvariantViolated>(true);
737 C.addTransition(State);
738 return;
739 }
740
741 const MemRegion *Region = getTrackRegion(*RetSVal);
742 if (!Region)
743 return;
744
745 const NullabilityState *TrackedNullability =
746 State->get<NullabilityMap>(Region);
747 if (TrackedNullability) {
748 Nullability TrackedNullabValue = TrackedNullability->getValue();
749 if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
750 Nullness != NullConstraint::IsNotNull &&
751 TrackedNullabValue == Nullability::Nullable &&
752 RequiredNullability == Nullability::Nonnull) {
753 static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
754 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
755
756 SmallString<256> SBuf;
757 llvm::raw_svector_ostream OS(SBuf);
758 OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
759 " that is expected to return a non-null value";
760
761 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
762 CK_NullableReturnedFromNonnull, N, Region, C);
763 }
764 return;
765 }
766 if (RequiredNullability == Nullability::Nullable) {
767 State = State->set<NullabilityMap>(Region,
768 NullabilityState(RequiredNullability,
769 S));
770 C.addTransition(State);
771 }
772}
773
774/// This callback warns when a nullable pointer or a null value is passed to a
775/// function that expects its argument to be nonnull.
776void NullabilityChecker::checkPreCall(const CallEvent &Call,
777 CheckerContext &C) const {
778 if (!Call.getDecl())
779 return;
780
781 ProgramStateRef State = C.getState();
782 if (State->get<InvariantViolated>())
783 return;
784
785 ProgramStateRef OrigState = State;
786
787 unsigned Idx = 0;
788 for (const ParmVarDecl *Param : Call.parameters()) {
789 if (Param->isParameterPack())
790 break;
791
792 if (Idx >= Call.getNumArgs())
793 break;
794
795 const Expr *ArgExpr = Call.getArgExpr(Idx);
796 auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
797 if (!ArgSVal)
798 continue;
799
800 if (!isValidPointerType(Param->getType()) &&
801 !Param->getType()->isReferenceType())
802 continue;
803
804 NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
805
806 Nullability RequiredNullability =
807 getNullabilityAnnotation(Param->getType());
808 Nullability ArgExprTypeLevelNullability =
810
811 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
812
813 if (ChecksEnabled[CK_NullPassedToNonnull] &&
814 Nullness == NullConstraint::IsNull &&
815 ArgExprTypeLevelNullability != Nullability::Nonnull &&
816 RequiredNullability == Nullability::Nonnull &&
817 isDiagnosableCall(Call)) {
818 ExplodedNode *N = C.generateErrorNode(State);
819 if (!N)
820 return;
821
822 SmallString<256> SBuf;
823 llvm::raw_svector_ostream OS(SBuf);
824 OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
825 OS << " passed to a callee that requires a non-null " << ParamIdx
826 << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
827 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
828 CK_NullPassedToNonnull, N, nullptr, C, ArgExpr,
829 /*SuppressPath=*/false);
830 return;
831 }
832
833 const MemRegion *Region = getTrackRegion(*ArgSVal);
834 if (!Region)
835 continue;
836
837 const NullabilityState *TrackedNullability =
838 State->get<NullabilityMap>(Region);
839
840 if (TrackedNullability) {
841 if (Nullness == NullConstraint::IsNotNull ||
842 TrackedNullability->getValue() != Nullability::Nullable)
843 continue;
844
845 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
846 RequiredNullability == Nullability::Nonnull &&
847 isDiagnosableCall(Call)) {
848 ExplodedNode *N = C.addTransition(State);
849 SmallString<256> SBuf;
850 llvm::raw_svector_ostream OS(SBuf);
851 OS << "Nullable pointer is passed to a callee that requires a non-null "
852 << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
853 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
854 CK_NullablePassedToNonnull, N, Region, C,
855 ArgExpr, /*SuppressPath=*/true);
856 return;
857 }
858 if (ChecksEnabled[CK_NullableDereferenced] &&
859 Param->getType()->isReferenceType()) {
860 ExplodedNode *N = C.addTransition(State);
861 reportBugIfInvariantHolds("Nullable pointer is dereferenced",
862 ErrorKind::NullableDereferenced,
863 CK_NullableDereferenced, N, Region, C,
864 ArgExpr, /*SuppressPath=*/true);
865 return;
866 }
867 continue;
868 }
869 }
870 if (State != OrigState)
871 C.addTransition(State);
872}
873
874/// Suppress the nullability warnings for some functions.
875void NullabilityChecker::checkPostCall(const CallEvent &Call,
876 CheckerContext &C) const {
877 auto Decl = Call.getDecl();
878 if (!Decl)
879 return;
880 // ObjC Messages handles in a different callback.
881 if (Call.getKind() == CE_ObjCMessage)
882 return;
883 const FunctionType *FuncType = Decl->getFunctionType();
884 if (!FuncType)
885 return;
886 QualType ReturnType = FuncType->getReturnType();
887 if (!isValidPointerType(ReturnType))
888 return;
889 ProgramStateRef State = C.getState();
890 if (State->get<InvariantViolated>())
891 return;
892
893 const MemRegion *Region = getTrackRegion(Call.getReturnValue());
894 if (!Region)
895 return;
896
897 // CG headers are misannotated. Do not warn for symbols that are the results
898 // of CG calls.
899 const SourceManager &SM = C.getSourceManager();
900 StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
901 if (llvm::sys::path::filename(FilePath).starts_with("CG")) {
902 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
903 C.addTransition(State);
904 return;
905 }
906
907 const NullabilityState *TrackedNullability =
908 State->get<NullabilityMap>(Region);
909
910 // ObjCMessageExpr gets the actual type through
911 // Sema::getMessageSendResultType, instead of using the return type of
912 // MethodDecl directly. The final type is generated by considering the
913 // nullability of receiver and MethodDecl together. Thus, The type of
914 // ObjCMessageExpr is prefer.
915 if (const Expr *E = Call.getOriginExpr())
916 ReturnType = E->getType();
917
918 if (!TrackedNullability &&
919 getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
920 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
921 C.addTransition(State);
922 }
923}
924
926 ProgramStateRef State) {
927 if (M.isReceiverSelfOrSuper()) {
928 // For super and super class receivers we assume that the receiver is
929 // nonnull.
930 return Nullability::Nonnull;
931 }
932 // Otherwise look up nullability in the state.
933 SVal Receiver = M.getReceiverSVal();
934 if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
935 // If the receiver is constrained to be nonnull, assume that it is nonnull
936 // regardless of its type.
937 NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
938 if (Nullness == NullConstraint::IsNotNull)
939 return Nullability::Nonnull;
940 }
941 auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
942 if (ValueRegionSVal) {
943 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
944 assert(SelfRegion);
945
946 const NullabilityState *TrackedSelfNullability =
947 State->get<NullabilityMap>(SelfRegion);
948 if (TrackedSelfNullability)
949 return TrackedSelfNullability->getValue();
950 }
951 return Nullability::Unspecified;
952}
953
954// The return value of a property access is typically a temporary value which
955// will not be tracked in a persistent manner by the analyzer. We use
956// evalAssume() in order to immediately record constraints on those temporaries
957// at the time they are imposed (e.g. by a nil-check conditional).
958ProgramStateRef NullabilityChecker::evalAssume(ProgramStateRef State, SVal Cond,
959 bool Assumption) const {
960 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
961 for (auto [PropKey, PropVal] : PropertyAccesses) {
962 if (!PropVal.isConstrainedNonnull) {
963 ConditionTruthVal IsNonNull = State->isNonNull(PropVal.Value);
964 if (IsNonNull.isConstrainedTrue()) {
965 ConstrainedPropertyVal Replacement = PropVal;
966 Replacement.isConstrainedNonnull = true;
967 State = State->set<PropertyAccessesMap>(PropKey, Replacement);
968 } else if (IsNonNull.isConstrainedFalse()) {
969 // Space optimization: no point in tracking constrained-null cases
970 State = State->remove<PropertyAccessesMap>(PropKey);
971 }
972 }
973 }
974
975 return State;
976}
977
978/// Calculate the nullability of the result of a message expr based on the
979/// nullability of the receiver, the nullability of the return value, and the
980/// constraints.
981void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
982 CheckerContext &C) const {
983 auto Decl = M.getDecl();
984 if (!Decl)
985 return;
986 QualType RetType = Decl->getReturnType();
987 if (!isValidPointerType(RetType))
988 return;
989
990 ProgramStateRef State = C.getState();
991 if (State->get<InvariantViolated>())
992 return;
993
994 const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
995 if (!ReturnRegion)
996 return;
997
998 auto Interface = Decl->getClassInterface();
999 auto Name = Interface ? Interface->getName() : "";
1000 // In order to reduce the noise in the diagnostics generated by this checker,
1001 // some framework and programming style based heuristics are used. These
1002 // heuristics are for Cocoa APIs which have NS prefix.
1003 if (Name.starts_with("NS")) {
1004 // Developers rely on dynamic invariants such as an item should be available
1005 // in a collection, or a collection is not empty often. Those invariants can
1006 // not be inferred by any static analysis tool. To not to bother the users
1007 // with too many false positives, every item retrieval function should be
1008 // ignored for collections. The instance methods of dictionaries in Cocoa
1009 // are either item retrieval related or not interesting nullability wise.
1010 // Using this fact, to keep the code easier to read just ignore the return
1011 // value of every instance method of dictionaries.
1012 if (M.isInstanceMessage() && Name.contains("Dictionary")) {
1013 State =
1014 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1015 C.addTransition(State);
1016 return;
1017 }
1018 // For similar reasons ignore some methods of Cocoa arrays.
1019 StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
1020 if (Name.contains("Array") &&
1021 (FirstSelectorSlot == "firstObject" ||
1022 FirstSelectorSlot == "lastObject")) {
1023 State =
1024 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1025 C.addTransition(State);
1026 return;
1027 }
1028
1029 // Encoding related methods of string should not fail when lossless
1030 // encodings are used. Using lossless encodings is so frequent that ignoring
1031 // this class of methods reduced the emitted diagnostics by about 30% on
1032 // some projects (and all of that was false positives).
1033 if (Name.contains("String")) {
1034 for (auto *Param : M.parameters()) {
1035 if (Param->getName() == "encoding") {
1036 State = State->set<NullabilityMap>(ReturnRegion,
1037 Nullability::Contradicted);
1038 C.addTransition(State);
1039 return;
1040 }
1041 }
1042 }
1043 }
1044
1045 const ObjCMessageExpr *Message = M.getOriginExpr();
1046 Nullability SelfNullability = getReceiverNullability(M, State);
1047
1048 const NullabilityState *NullabilityOfReturn =
1049 State->get<NullabilityMap>(ReturnRegion);
1050
1051 if (NullabilityOfReturn) {
1052 // When we have a nullability tracked for the return value, the nullability
1053 // of the expression will be the most nullable of the receiver and the
1054 // return value.
1055 Nullability RetValTracked = NullabilityOfReturn->getValue();
1056 Nullability ComputedNullab =
1057 getMostNullable(RetValTracked, SelfNullability);
1058 if (ComputedNullab != RetValTracked &&
1059 ComputedNullab != Nullability::Unspecified) {
1060 const Stmt *NullabilitySource =
1061 ComputedNullab == RetValTracked
1062 ? NullabilityOfReturn->getNullabilitySource()
1063 : Message->getInstanceReceiver();
1064 State = State->set<NullabilityMap>(
1065 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1066 C.addTransition(State);
1067 }
1068 return;
1069 }
1070
1071 // No tracked information. Use static type information for return value.
1072 Nullability RetNullability = getNullabilityAnnotation(Message->getType());
1073
1074 // Properties might be computed, which means the property value could
1075 // theoretically change between calls even in commonly-observed cases like
1076 // this:
1077 //
1078 // if (foo.prop) { // ok, it's nonnull here...
1079 // [bar doStuffWithNonnullVal:foo.prop]; // ...but what about
1080 // here?
1081 // }
1082 //
1083 // If the property is nullable-annotated, a naive analysis would lead to many
1084 // false positives despite the presence of probably-correct nil-checks. To
1085 // reduce the false positive rate, we maintain a history of the most recently
1086 // observed property value. For each property access, if the prior value has
1087 // been constrained to be not nil then we will conservatively assume that the
1088 // next access can be inferred as nonnull.
1089 if (RetNullability != Nullability::Nonnull &&
1090 M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined) {
1091 bool LookupResolved = false;
1092 if (const MemRegion *ReceiverRegion = getTrackRegion(M.getReceiverSVal())) {
1093 if (const IdentifierInfo *Ident =
1095 LookupResolved = true;
1096 ObjectPropPair Key = std::make_pair(ReceiverRegion, Ident);
1097 const ConstrainedPropertyVal *PrevPropVal =
1098 State->get<PropertyAccessesMap>(Key);
1099 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1100 RetNullability = Nullability::Nonnull;
1101 } else {
1102 // If a previous property access was constrained as nonnull, we hold
1103 // on to that constraint (effectively inferring that all subsequent
1104 // accesses on that code path can be inferred as nonnull). If the
1105 // previous property access was *not* constrained as nonnull, then
1106 // let's throw it away in favor of keeping the SVal associated with
1107 // this more recent access.
1108 if (auto ReturnSVal =
1110 State = State->set<PropertyAccessesMap>(
1111 Key, ConstrainedPropertyVal(*ReturnSVal));
1112 }
1113 }
1114 }
1115 }
1116
1117 if (!LookupResolved) {
1118 // Fallback: err on the side of suppressing the false positive.
1119 RetNullability = Nullability::Nonnull;
1120 }
1121 }
1122
1123 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1124 if (ComputedNullab == Nullability::Nullable) {
1125 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1126 ? Message
1127 : Message->getInstanceReceiver();
1128 State = State->set<NullabilityMap>(
1129 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1130 C.addTransition(State);
1131 }
1132}
1133
1134/// Explicit casts are trusted. If there is a disagreement in the nullability
1135/// annotations in the destination and the source or '0' is casted to nonnull
1136/// track the value as having contraditory nullability. This will allow users to
1137/// suppress warnings.
1138void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
1139 CheckerContext &C) const {
1140 QualType OriginType = CE->getSubExpr()->getType();
1141 QualType DestType = CE->getType();
1142 if (!isValidPointerType(OriginType))
1143 return;
1144 if (!isValidPointerType(DestType))
1145 return;
1146
1147 ProgramStateRef State = C.getState();
1148 if (State->get<InvariantViolated>())
1149 return;
1150
1151 Nullability DestNullability = getNullabilityAnnotation(DestType);
1152
1153 // No explicit nullability in the destination type, so this cast does not
1154 // change the nullability.
1155 if (DestNullability == Nullability::Unspecified)
1156 return;
1157
1158 auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
1159 const MemRegion *Region = getTrackRegion(*RegionSVal);
1160 if (!Region)
1161 return;
1162
1163 // When 0 is converted to nonnull mark it as contradicted.
1164 if (DestNullability == Nullability::Nonnull) {
1165 NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
1166 if (Nullness == NullConstraint::IsNull) {
1167 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1168 C.addTransition(State);
1169 return;
1170 }
1171 }
1172
1173 const NullabilityState *TrackedNullability =
1174 State->get<NullabilityMap>(Region);
1175
1176 if (!TrackedNullability) {
1177 if (DestNullability != Nullability::Nullable)
1178 return;
1179 State = State->set<NullabilityMap>(Region,
1180 NullabilityState(DestNullability, CE));
1181 C.addTransition(State);
1182 return;
1183 }
1184
1185 if (TrackedNullability->getValue() != DestNullability &&
1186 TrackedNullability->getValue() != Nullability::Contradicted) {
1187 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1188 C.addTransition(State);
1189 }
1190}
1191
1192/// For a given statement performing a bind, attempt to syntactically
1193/// match the expression resulting in the bound value.
1194static const Expr * matchValueExprForBind(const Stmt *S) {
1195 // For `x = e` the value expression is the right-hand side.
1196 if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1197 if (BinOp->getOpcode() == BO_Assign)
1198 return BinOp->getRHS();
1199 }
1200
1201 // For `int x = e` the value expression is the initializer.
1202 if (auto *DS = dyn_cast<DeclStmt>(S)) {
1203 if (DS->isSingleDecl()) {
1204 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1205 if (!VD)
1206 return nullptr;
1207
1208 if (const Expr *Init = VD->getInit())
1209 return Init;
1210 }
1211 }
1212
1213 return nullptr;
1214}
1215
1216/// Returns true if \param S is a DeclStmt for a local variable that
1217/// ObjC automated reference counting initialized with zero.
1219 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1220 // prevents false positives when a _Nonnull local variable cannot be
1221 // initialized with an initialization expression:
1222 // NSString * _Nonnull s; // no-warning
1223 // @autoreleasepool {
1224 // s = ...
1225 // }
1226 //
1227 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1228 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1229 // the zero-initialized definition will unexpectedly yield nil.
1230
1231 // Locals are only zero-initialized when automated reference counting
1232 // is turned on.
1233 if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
1234 return false;
1235
1236 auto *DS = dyn_cast<DeclStmt>(S);
1237 if (!DS || !DS->isSingleDecl())
1238 return false;
1239
1240 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1241 if (!VD)
1242 return false;
1243
1244 // Sema only zero-initializes locals with ObjCLifetimes.
1245 if(!VD->getType().getQualifiers().hasObjCLifetime())
1246 return false;
1247
1248 const Expr *Init = VD->getInit();
1249 assert(Init && "ObjC local under ARC without initializer");
1250
1251 // Return false if the local is explicitly initialized (e.g., with '= nil').
1252 if (!isa<ImplicitValueInitExpr>(Init))
1253 return false;
1254
1255 return true;
1256}
1257
1258/// Propagate the nullability information through binds and warn when nullable
1259/// pointer or null symbol is assigned to a pointer with a nonnull type.
1260void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
1261 CheckerContext &C) const {
1262 const TypedValueRegion *TVR =
1263 dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
1264 if (!TVR)
1265 return;
1266
1267 QualType LocType = TVR->getValueType();
1268 if (!isValidPointerType(LocType))
1269 return;
1270
1271 ProgramStateRef State = C.getState();
1272 if (State->get<InvariantViolated>())
1273 return;
1274
1275 auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1276 if (!ValDefOrUnknown)
1277 return;
1278
1279 NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1280
1281 Nullability ValNullability = Nullability::Unspecified;
1282 if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1283 ValNullability = getNullabilityAnnotation(Sym->getType());
1284
1285 Nullability LocNullability = getNullabilityAnnotation(LocType);
1286
1287 // If the type of the RHS expression is nonnull, don't warn. This
1288 // enables explicit suppression with a cast to nonnull.
1289 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1290 const Expr *ValueExpr = matchValueExprForBind(S);
1291 if (ValueExpr) {
1292 ValueExprTypeLevelNullability =
1294 }
1295
1296 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1297 RhsNullness == NullConstraint::IsNull);
1298 if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
1299 ValNullability != Nullability::Nonnull &&
1300 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1302 static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
1303 ExplodedNode *N = C.generateErrorNode(State, &Tag);
1304 if (!N)
1305 return;
1306
1307
1308 const Stmt *ValueStmt = S;
1309 if (ValueExpr)
1310 ValueStmt = ValueExpr;
1311
1312 SmallString<256> SBuf;
1313 llvm::raw_svector_ostream OS(SBuf);
1314 OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
1315 OS << " assigned to a pointer which is expected to have non-null value";
1316 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1317 CK_NullPassedToNonnull, N, nullptr, C, ValueStmt);
1318 return;
1319 }
1320
1321 // If null was returned from a non-null function, mark the nullability
1322 // invariant as violated even if the diagnostic was suppressed.
1323 if (NullAssignedToNonNull) {
1324 State = State->set<InvariantViolated>(true);
1325 C.addTransition(State);
1326 return;
1327 }
1328
1329 // Intentionally missing case: '0' is bound to a reference. It is handled by
1330 // the DereferenceChecker.
1331
1332 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1333 if (!ValueRegion)
1334 return;
1335
1336 const NullabilityState *TrackedNullability =
1337 State->get<NullabilityMap>(ValueRegion);
1338
1339 if (TrackedNullability) {
1340 if (RhsNullness == NullConstraint::IsNotNull ||
1341 TrackedNullability->getValue() != Nullability::Nullable)
1342 return;
1343 if (ChecksEnabled[CK_NullablePassedToNonnull] &&
1344 LocNullability == Nullability::Nonnull) {
1345 static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1346 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
1347 reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1348 "which is expected to have non-null value",
1349 ErrorKind::NullableAssignedToNonnull,
1350 CK_NullablePassedToNonnull, N, ValueRegion, C);
1351 }
1352 return;
1353 }
1354
1355 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1356
1357 if (ValNullability == Nullability::Nullable) {
1358 // Trust the static information of the value more than the static
1359 // information on the location.
1360 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1361 State = State->set<NullabilityMap>(
1362 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1363 C.addTransition(State);
1364 return;
1365 }
1366
1367 if (LocNullability == Nullability::Nullable) {
1368 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1369 State = State->set<NullabilityMap>(
1370 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1371 C.addTransition(State);
1372 }
1373}
1374
1375void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1376 const char *NL, const char *Sep) const {
1377
1378 NullabilityMapTy B = State->get<NullabilityMap>();
1379
1380 if (State->get<InvariantViolated>())
1381 Out << Sep << NL
1382 << "Nullability invariant was violated, warnings suppressed." << NL;
1383
1384 if (B.isEmpty())
1385 return;
1386
1387 if (!State->get<InvariantViolated>())
1388 Out << Sep << NL;
1389
1390 for (auto [Region, State] : B) {
1391 Out << Region << " : ";
1392 State.print(Out);
1393 Out << NL;
1394 }
1395}
1396
1397void ento::registerNullabilityBase(CheckerManager &mgr) {
1398 mgr.registerChecker<NullabilityChecker>();
1399}
1400
1401bool ento::shouldRegisterNullabilityBase(const CheckerManager &mgr) {
1402 return true;
1403}
1404
1405#define REGISTER_CHECKER(name, trackingRequired) \
1406 void ento::register##name##Checker(CheckerManager &mgr) { \
1407 NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
1408 checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
1409 checker->CheckNames[NullabilityChecker::CK_##name] = \
1410 mgr.getCurrentCheckerName(); \
1411 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
1412 checker->NoDiagnoseCallsToSystemHeaders = \
1413 checker->NoDiagnoseCallsToSystemHeaders || \
1414 mgr.getAnalyzerOptions().getCheckerBooleanOption( \
1415 checker, "NoDiagnoseCallsToSystemHeaders", true); \
1416 } \
1417 \
1418 bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
1419 return true; \
1420 }
1421
1422// The checks are likely to be turned on by default and it is possible to do
1423// them without tracking any nullability related information. As an optimization
1424// no nullability information will be tracked when only these two checks are
1425// enables.
1426REGISTER_CHECKER(NullPassedToNonnull, false)
1427REGISTER_CHECKER(NullReturnedFromNonnull, false)
1428
1429REGISTER_CHECKER(NullableDereferenced, true)
1430REGISTER_CHECKER(NullablePassedToNonnull, true)
1431REGISTER_CHECKER(NullableReturnedFromNonnull, true)
#define V(N, I)
Definition: ASTContext.h:3443
#define SM(sm)
Definition: Cuda.cpp:84
const Decl * D
Expr * E
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
#define X(type, name)
Definition: Value.h:144
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:3597
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
Definition: DeclBase.cpp:1179
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
ExplicitCastExpr - An explicit cast written in the source code.
Definition: Expr.h:3799
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:3070
QualType getType() const
Definition: Expr.h:142
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:4321
QualType getReturnType() const
Definition: Type.h:4643
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:1153
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:941
Represents a pointer to an Objective C object.
Definition: Type.h:7580
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
Definition: Type.h:7632
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Definition: Attr.h:255
Represents a parameter to a function.
Definition: Decl.h:1725
A (possibly-)qualified type.
Definition: Type.h:929
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3046
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:8200
bool isObjCObjectPointerType() const
Definition: Type.h:8328
bool isAnyPointerType() const
Definition: Type.h:8194
QualType getType() const
Definition: Decl.h:682
Represents a statement that could possibly have a value and type.
Definition: Stmt.h:2039
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:323
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:1199
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:97
const RegionTy * getAs() const
Definition: MemRegion.h:1388
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:1248
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Definition: CallEvent.h:1278
bool isInstanceMessage() const
Definition: CallEvent.h:1288
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
Definition: CallEvent.cpp:1075
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:1274
ArrayRef< ParmVarDecl * > parameters() const override
Return call's formal parameters.
Definition: CallEvent.cpp:982
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:1014
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Definition: CallEvent.cpp:1030
Selector getSelector() const
Definition: CallEvent.h:1296
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:56
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:87
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:446
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:780
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:535
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:1243
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool IsNonNull(InterpState &S, CodePtr OpPC)
Definition: Interp.h:2433
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:204
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:25
#define false
Definition: stdbool.h:26
We dereferenced a location that may be null.
Definition: Checker.h:548