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