clang 23.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,
152 BugReporterContext &BRC,
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]
246 DefinedOrUnknownSVal Value;
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,
341 PathSensitiveBugReport &BR) {
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.
370 PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
371 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
372}
373
374/// Returns true when the value stored at the given location has been
375/// constrained to null after being passed through an object of nonnnull type.
377 SVal LV, QualType T) {
378 if (getNullabilityAnnotation(T) != Nullability::Nonnull)
379 return false;
380
381 auto RegionVal = LV.getAs<loc::MemRegionVal>();
382 if (!RegionVal)
383 return false;
384
385 // If the value was constrained to null *after* it was passed through that
386 // location, it could not have been a concrete pointer *when* it was passed.
387 // In that case we would have handled the situation when the value was
388 // bound to that location, by emitting (or not emitting) a report.
389 // Therefore we are only interested in symbolic regions that can be either
390 // null or non-null depending on the value of their respective symbol.
391 auto StoredVal = State->getSVal(*RegionVal).getAs<loc::MemRegionVal>();
392 if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
393 return false;
394
395 if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
396 return true;
397
398 return false;
399}
400
402 ProgramStateRef State,
403 const StackFrame *SF) {
404 for (const auto *ParamDecl : Params) {
405 if (ParamDecl->isParameterPack())
406 break;
407
408 SVal LV = State->getLValue(ParamDecl, SF);
410 ParamDecl->getType())) {
411 return true;
412 }
413 }
414 return false;
415}
416
418 const StackFrame *SF) {
419 auto *MD = dyn_cast<ObjCMethodDecl>(SF->getDecl());
420 if (!MD || !MD->isInstanceMethod())
421 return false;
422
423 const ImplicitParamDecl *SelfDecl = SF->getSelfDecl();
424 if (!SelfDecl)
425 return false;
426
427 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, SF));
428
429 const ObjCObjectPointerType *SelfType =
430 dyn_cast<ObjCObjectPointerType>(SelfDecl->getType());
431 if (!SelfType)
432 return false;
433
434 const ObjCInterfaceDecl *ID = SelfType->getInterfaceDecl();
435 if (!ID)
436 return false;
437
438 for (const auto *IvarDecl : ID->ivars()) {
439 SVal LV = State->getLValue(IvarDecl, SelfVal);
440 if (checkValueAtLValForInvariantViolation(State, LV, IvarDecl->getType())) {
441 return true;
442 }
443 }
444 return false;
445}
446
448 CheckerContext &C) {
449 if (State->get<InvariantViolated>())
450 return true;
451
452 const StackFrame *SF = C.getStackFrame();
453 const Decl *D = SF->getDecl();
454 if (!D)
455 return false;
456
458 if (const auto *BD = dyn_cast<BlockDecl>(D))
459 Params = BD->parameters();
460 else if (const auto *FD = dyn_cast<FunctionDecl>(D))
461 Params = FD->parameters();
462 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
463 Params = MD->parameters();
464 else
465 return false;
466
467 if (checkParamsForPreconditionViolation(Params, State, SF) ||
469 if (!N->isSink())
470 C.addTransition(State->set<InvariantViolated>(true), N);
471 return true;
472 }
473 return false;
474}
475
476void NullabilityChecker::reportBugIfInvariantHolds(
477 StringRef Msg, ErrorKind Error, const BugType &BT, ExplodedNode *N,
478 const MemRegion *Region, CheckerContext &C, const Stmt *ValueExpr,
479 bool SuppressPath) const {
480 ProgramStateRef OriginalState = N->getState();
481
482 if (checkInvariantViolation(OriginalState, N, C))
483 return;
484 if (SuppressPath) {
485 OriginalState = OriginalState->set<InvariantViolated>(true);
486 N = C.addTransition(OriginalState, N);
487 }
488
489 reportBug(Msg, Error, BT, N, Region, C.getBugReporter(), ValueExpr);
490}
491
492/// Cleaning up the program state.
493void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
494 CheckerContext &C) const {
495 ProgramStateRef State = C.getState();
496 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
497 for (const MemRegion *Reg : llvm::make_first_range(Nullabilities)) {
498 const auto *Region = Reg->getAs<SymbolicRegion>();
499 assert(Region && "Non-symbolic region is tracked.");
500 if (SR.isDead(Region->getSymbol())) {
501 State = State->remove<NullabilityMap>(Reg);
502 }
503 }
504
505 // When an object goes out of scope, we can free the history associated
506 // with any property accesses on that object
507 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
508 for (ObjectPropPair PropKey : llvm::make_first_range(PropertyAccesses)) {
509 const MemRegion *ReceiverRegion = PropKey.first;
510 if (!SR.isLiveRegion(ReceiverRegion)) {
511 State = State->remove<PropertyAccessesMap>(PropKey);
512 }
513 }
514
515 // When one of the nonnull arguments are constrained to be null, nullability
516 // preconditions are violated. It is not enough to check this only when we
517 // actually report an error, because at that time interesting symbols might be
518 // reaped.
519 if (checkInvariantViolation(State, C.getPredecessor(), C))
520 return;
521 C.addTransition(State);
522}
523
524/// This callback triggers when a pointer is dereferenced and the analyzer does
525/// not know anything about the value of that pointer. When that pointer is
526/// nullable, this code emits a warning.
527void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
528 if (Event.SinkNode->getState()->get<InvariantViolated>())
529 return;
530
531 const MemRegion *Region =
532 getTrackRegion(Event.Location, /*CheckSuperRegion=*/true);
533 if (!Region)
534 return;
535
536 ProgramStateRef State = Event.SinkNode->getState();
537 const NullabilityState *TrackedNullability =
538 State->get<NullabilityMap>(Region);
539
540 if (!TrackedNullability)
541 return;
542
543 if (NullableDereferenced.isEnabled() &&
544 TrackedNullability->getValue() == Nullability::Nullable) {
545 BugReporter &BR = *Event.BR;
546 // Do not suppress errors on defensive code paths, because dereferencing
547 // a nullable pointer is always an error.
548 if (Event.IsDirectDereference)
549 reportBug("Nullable pointer is dereferenced",
550 ErrorKind::NullableDereferenced, NullableDereferenced,
551 Event.SinkNode, Region, BR);
552 else {
553 reportBug("Nullable pointer is passed to a callee that requires a "
554 "non-null",
555 ErrorKind::NullablePassedToNonnull, NullableDereferenced,
556 Event.SinkNode, Region, BR);
557 }
558 }
559}
560
561void NullabilityChecker::checkBeginFunction(CheckerContext &C) const {
562 if (!C.inTopFrame())
563 return;
564
565 const StackFrame *SF = C.getStackFrame();
566 auto AbstractCall = AnyCall::forDecl(SF->getDecl());
567 if (!AbstractCall || AbstractCall->parameters().empty())
568 return;
569
570 ProgramStateRef State = C.getState();
571 for (const ParmVarDecl *Param : AbstractCall->parameters()) {
572 if (!isValidPointerType(Param->getType()))
573 continue;
574
575 Nullability RequiredNullability =
576 getNullabilityAnnotation(Param->getType());
577 if (RequiredNullability != Nullability::Nullable)
578 continue;
579
580 const VarRegion *ParamRegion = State->getRegion(Param, SF);
581 const MemRegion *ParamPointeeRegion =
582 State->getSVal(ParamRegion).getAsRegion();
583 if (!ParamPointeeRegion)
584 continue;
585
586 State = State->set<NullabilityMap>(ParamPointeeRegion,
587 NullabilityState(RequiredNullability));
588 }
589 C.addTransition(State);
590}
591
592// Whenever we see a load from a typed memory region that's been annotated as
593// 'nonnull', we want to trust the user on that and assume that it is is indeed
594// non-null.
595//
596// We do so even if the value is known to have been assigned to null.
597// The user should be warned on assigning the null value to a non-null pointer
598// as opposed to warning on the later dereference of this pointer.
599//
600// \code
601// int * _Nonnull var = 0; // we want to warn the user here...
602// // . . .
603// *var = 42; // ...and not here
604// \endcode
605void NullabilityChecker::checkLocation(SVal Location, bool IsLoad,
606 const Stmt *S,
607 CheckerContext &Context) const {
608 // We should care only about loads.
609 // The main idea is to add a constraint whenever we're loading a value from
610 // an annotated pointer type.
611 if (!IsLoad)
612 return;
613
614 // Annotations that we want to consider make sense only for types.
615 const auto *Region =
616 dyn_cast_or_null<TypedValueRegion>(Location.getAsRegion());
617 if (!Region)
618 return;
619
620 ProgramStateRef State = Context.getState();
621
622 auto StoredVal = State->getSVal(Region).getAs<loc::MemRegionVal>();
623 if (!StoredVal)
624 return;
625
626 Nullability NullabilityOfTheLoadedValue =
627 getNullabilityAnnotation(Region->getValueType());
628
629 if (NullabilityOfTheLoadedValue == Nullability::Nonnull) {
630 // It doesn't matter what we think about this particular pointer, it should
631 // be considered non-null as annotated by the developer.
632 if (ProgramStateRef NewState = State->assume(*StoredVal, true)) {
633 Context.addTransition(NewState);
634 }
635 }
636}
637
638/// Find the outermost subexpression of E that is not an implicit cast.
639/// This looks through the implicit casts to _Nonnull that ARC adds to
640/// return expressions of ObjC types when the return type of the function or
641/// method is non-null but the express is not.
642static const Expr *lookThroughImplicitCasts(const Expr *E) {
643 return E->IgnoreImpCasts();
644}
645
646/// This method check when nullable pointer or null value is returned from a
647/// function that has nonnull return type.
648void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
649 CheckerContext &C) const {
650 auto RetExpr = S->getRetValue();
651 if (!RetExpr)
652 return;
653
654 if (!isValidPointerType(RetExpr->getType()))
655 return;
656
657 ProgramStateRef State = C.getState();
658 if (State->get<InvariantViolated>())
659 return;
660
661 auto RetSVal = C.getSVal(RetExpr).getAs<DefinedOrUnknownSVal>();
662 if (!RetSVal)
663 return;
664
665 bool InSuppressedMethodFamily = false;
666
667 QualType RequiredRetType;
668 AnalysisDeclContext *DeclCtxt = C.getStackFrame()->getAnalysisDeclContext();
669 const Decl *D = DeclCtxt->getDecl();
670 if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
671 // HACK: This is a big hammer to avoid warning when there are defensive
672 // nil checks in -init and -copy methods. We should add more sophisticated
673 // logic here to suppress on common defensive idioms but still
674 // warn when there is a likely problem.
675 ObjCMethodFamily Family = MD->getMethodFamily();
676 if (OMF_init == Family || OMF_copy == Family || OMF_mutableCopy == Family)
677 InSuppressedMethodFamily = true;
678
679 RequiredRetType = MD->getReturnType();
680 } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
681 RequiredRetType = FD->getReturnType();
682 } else {
683 return;
684 }
685
686 NullConstraint Nullness = getNullConstraint(*RetSVal, State);
687
688 Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
689 if (const auto *FunDecl = C.getStackFrame()->getDecl();
690 FunDecl && FunDecl->getAttr<ReturnsNonNullAttr>() &&
691 (RequiredNullability == Nullability::Unspecified ||
692 RequiredNullability == Nullability::Nullable)) {
693 // If a function is marked with the returns_nonnull attribute,
694 // the return value must be non-null.
695 RequiredNullability = Nullability::Nonnull;
696 }
697
698 // If the returned value is null but the type of the expression
699 // generating it is nonnull then we will suppress the diagnostic.
700 // This enables explicit suppression when returning a nil literal in a
701 // function with a _Nonnull return type:
702 // return (NSString * _Nonnull)0;
703 Nullability RetExprTypeLevelNullability =
705
706 if (RequiredNullability == Nullability::Nonnull &&
707 Nullness == NullConstraint::IsNull) {
708 if (NullReturnedFromNonnull.isEnabled() &&
709 RetExprTypeLevelNullability != Nullability::Nonnull &&
710 !InSuppressedMethodFamily) {
711 ExplodedNode *N = C.generateErrorNode(State);
712 if (!N)
713 return;
714
715 SmallString<256> SBuf;
716 llvm::raw_svector_ostream OS(SBuf);
717 OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
718 OS << " returned from a " << C.getDeclDescription(D)
719 << " that is expected to return a non-null value";
720 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
721 NullReturnedFromNonnull, N, nullptr, C,
722 RetExpr);
723 return;
724 }
725
726 // If null was returned from a non-null function, mark the nullability
727 // invariant as violated even if the diagnostic was suppressed.
728 State = State->set<InvariantViolated>(true);
729 C.addTransition(State);
730 return;
731 }
732
733 const MemRegion *Region = getTrackRegion(*RetSVal);
734 if (!Region)
735 return;
736
737 const NullabilityState *TrackedNullability =
738 State->get<NullabilityMap>(Region);
739 if (TrackedNullability) {
740 Nullability TrackedNullabValue = TrackedNullability->getValue();
741 if (NullableReturnedFromNonnull.isEnabled() &&
742 Nullness != NullConstraint::IsNotNull &&
743 TrackedNullabValue == Nullability::Nullable &&
744 RequiredNullability == Nullability::Nonnull) {
745 ExplodedNode *N = C.addTransition(State, C.getPredecessor());
746
747 SmallString<256> SBuf;
748 llvm::raw_svector_ostream OS(SBuf);
749 OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
750 " that is expected to return a non-null value";
751
752 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
753 NullableReturnedFromNonnull, N, Region, C);
754 }
755 return;
756 }
757 if (RequiredNullability == Nullability::Nullable) {
758 State = State->set<NullabilityMap>(Region,
759 NullabilityState(RequiredNullability,
760 S));
761 C.addTransition(State);
762 }
763}
764
765/// This callback warns when a nullable pointer or a null value is passed to a
766/// function that expects its argument to be nonnull.
767void NullabilityChecker::checkPreCall(const CallEvent &Call,
768 CheckerContext &C) const {
769 if (!Call.getDecl())
770 return;
771
772 ProgramStateRef State = C.getState();
773 if (State->get<InvariantViolated>())
774 return;
775
776 ProgramStateRef OrigState = State;
777
778 unsigned Idx = 0;
779 for (const ParmVarDecl *Param : Call.parameters()) {
780 if (Param->isParameterPack())
781 break;
782
783 if (Idx >= Call.getNumArgs())
784 break;
785
786 const Expr *ArgExpr = Call.getArgExpr(Idx);
787 auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
788 if (!ArgSVal)
789 continue;
790
791 if (!isValidPointerType(Param->getType()) &&
792 !Param->getType()->isReferenceType())
793 continue;
794
795 NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
796
797 Nullability RequiredNullability =
798 getNullabilityAnnotation(Param->getType());
799 Nullability ArgExprTypeLevelNullability =
801
802 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
803
804 if (NullPassedToNonnull.isEnabled() && Nullness == NullConstraint::IsNull &&
805 ArgExprTypeLevelNullability != Nullability::Nonnull &&
806 RequiredNullability == Nullability::Nonnull &&
807 isDiagnosableCall(Call)) {
808 ExplodedNode *N = C.generateErrorNode(State);
809 if (!N)
810 return;
811
812 SmallString<256> SBuf;
813 llvm::raw_svector_ostream OS(SBuf);
814 OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
815 OS << " passed to a callee that requires a non-null " << ParamIdx
816 << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
817 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
818 NullPassedToNonnull, N, nullptr, C, ArgExpr,
819 /*SuppressPath=*/false);
820 return;
821 }
822
823 const MemRegion *Region = getTrackRegion(*ArgSVal);
824 if (!Region)
825 continue;
826
827 const NullabilityState *TrackedNullability =
828 State->get<NullabilityMap>(Region);
829
830 if (TrackedNullability) {
831 if (Nullness == NullConstraint::IsNotNull ||
832 TrackedNullability->getValue() != Nullability::Nullable)
833 continue;
834
835 if (NullablePassedToNonnull.isEnabled() &&
836 RequiredNullability == Nullability::Nonnull &&
837 isDiagnosableCall(Call)) {
838 ExplodedNode *N = C.addTransition(State);
839 SmallString<256> SBuf;
840 llvm::raw_svector_ostream OS(SBuf);
841 OS << "Nullable pointer is passed to a callee that requires a non-null "
842 << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
843 reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
844 NullablePassedToNonnull, N, Region, C,
845 ArgExpr, /*SuppressPath=*/true);
846 return;
847 }
848 if (NullableDereferenced.isEnabled() &&
849 Param->getType()->isReferenceType()) {
850 ExplodedNode *N = C.addTransition(State);
851 reportBugIfInvariantHolds(
852 "Nullable pointer is dereferenced", ErrorKind::NullableDereferenced,
853 NullableDereferenced, N, Region, C, ArgExpr, /*SuppressPath=*/true);
854 return;
855 }
856 continue;
857 }
858 }
859 if (State != OrigState)
860 C.addTransition(State);
861}
862
863/// Suppress the nullability warnings for some functions.
864void NullabilityChecker::checkPostCall(const CallEvent &Call,
865 CheckerContext &C) const {
866 auto Decl = Call.getDecl();
867 if (!Decl)
868 return;
869 // ObjC Messages handles in a different callback.
870 if (Call.getKind() == CE_ObjCMessage)
871 return;
872 const FunctionType *FuncType = Decl->getFunctionType();
873 if (!FuncType)
874 return;
875 QualType ReturnType = FuncType->getReturnType();
876 if (!isValidPointerType(ReturnType))
877 return;
878 ProgramStateRef State = C.getState();
879 if (State->get<InvariantViolated>())
880 return;
881
882 const MemRegion *Region = getTrackRegion(Call.getReturnValue());
883 if (!Region)
884 return;
885
886 // CG headers are misannotated. Do not warn for symbols that are the results
887 // of CG calls.
888 const SourceManager &SM = C.getSourceManager();
889 StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
890 if (llvm::sys::path::filename(FilePath).starts_with("CG")) {
891 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
892 C.addTransition(State);
893 return;
894 }
895
896 const NullabilityState *TrackedNullability =
897 State->get<NullabilityMap>(Region);
898
899 // ObjCMessageExpr gets the actual type through
900 // Sema::getMessageSendResultType, instead of using the return type of
901 // MethodDecl directly. The final type is generated by considering the
902 // nullability of receiver and MethodDecl together. Thus, The type of
903 // ObjCMessageExpr is prefer.
904 if (const Expr *E = Call.getOriginExpr())
905 ReturnType = E->getType();
906
907 if (!TrackedNullability &&
908 getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
909 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
910 C.addTransition(State);
911 }
912}
913
915 ProgramStateRef State) {
916 if (M.isReceiverSelfOrSuper()) {
917 // For super and super class receivers we assume that the receiver is
918 // nonnull.
919 return Nullability::Nonnull;
920 }
921 // Otherwise look up nullability in the state.
922 SVal Receiver = M.getReceiverSVal();
923 if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
924 // If the receiver is constrained to be nonnull, assume that it is nonnull
925 // regardless of its type.
926 NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
927 if (Nullness == NullConstraint::IsNotNull)
928 return Nullability::Nonnull;
929 }
930 auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
931 if (ValueRegionSVal) {
932 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
933 assert(SelfRegion);
934
935 const NullabilityState *TrackedSelfNullability =
936 State->get<NullabilityMap>(SelfRegion);
937 if (TrackedSelfNullability)
938 return TrackedSelfNullability->getValue();
939 }
940 return Nullability::Unspecified;
941}
942
943// The return value of a property access is typically a temporary value which
944// will not be tracked in a persistent manner by the analyzer. We use
945// evalAssume() in order to immediately record constraints on those temporaries
946// at the time they are imposed (e.g. by a nil-check conditional).
947ProgramStateRef NullabilityChecker::evalAssume(ProgramStateRef State, SVal Cond,
948 bool Assumption) const {
949 PropertyAccessesMapTy PropertyAccesses = State->get<PropertyAccessesMap>();
950 for (auto [PropKey, PropVal] : PropertyAccesses) {
951 if (!PropVal.isConstrainedNonnull) {
952 ConditionTruthVal IsNonNull = State->isNonNull(PropVal.Value);
953 if (IsNonNull.isConstrainedTrue()) {
954 ConstrainedPropertyVal Replacement = PropVal;
955 Replacement.isConstrainedNonnull = true;
956 State = State->set<PropertyAccessesMap>(PropKey, Replacement);
957 } else if (IsNonNull.isConstrainedFalse()) {
958 // Space optimization: no point in tracking constrained-null cases
959 State = State->remove<PropertyAccessesMap>(PropKey);
960 }
961 }
962 }
963
964 return State;
965}
966
967/// Calculate the nullability of the result of a message expr based on the
968/// nullability of the receiver, the nullability of the return value, and the
969/// constraints.
970void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
971 CheckerContext &C) const {
972 auto Decl = M.getDecl();
973 if (!Decl)
974 return;
975 QualType RetType = Decl->getReturnType();
976 if (!isValidPointerType(RetType))
977 return;
978
979 ProgramStateRef State = C.getState();
980 if (State->get<InvariantViolated>())
981 return;
982
983 const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
984 if (!ReturnRegion)
985 return;
986
987 auto Interface = Decl->getClassInterface();
988 auto Name = Interface ? Interface->getName() : "";
989 // In order to reduce the noise in the diagnostics generated by this checker,
990 // some framework and programming style based heuristics are used. These
991 // heuristics are for Cocoa APIs which have NS prefix.
992 if (Name.starts_with("NS")) {
993 // Developers rely on dynamic invariants such as an item should be available
994 // in a collection, or a collection is not empty often. Those invariants can
995 // not be inferred by any static analysis tool. To not to bother the users
996 // with too many false positives, every item retrieval function should be
997 // ignored for collections. The instance methods of dictionaries in Cocoa
998 // are either item retrieval related or not interesting nullability wise.
999 // Using this fact, to keep the code easier to read just ignore the return
1000 // value of every instance method of dictionaries.
1001 if (M.isInstanceMessage() && Name.contains("Dictionary")) {
1002 State =
1003 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1004 C.addTransition(State);
1005 return;
1006 }
1007 // For similar reasons ignore some methods of Cocoa arrays.
1008 StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
1009 if (Name.contains("Array") &&
1010 (FirstSelectorSlot == "firstObject" ||
1011 FirstSelectorSlot == "lastObject")) {
1012 State =
1013 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
1014 C.addTransition(State);
1015 return;
1016 }
1017
1018 // Encoding related methods of string should not fail when lossless
1019 // encodings are used. Using lossless encodings is so frequent that ignoring
1020 // this class of methods reduced the emitted diagnostics by about 30% on
1021 // some projects (and all of that was false positives).
1022 if (Name.contains("String")) {
1023 for (auto *Param : M.parameters()) {
1024 if (Param->getName() == "encoding") {
1025 State = State->set<NullabilityMap>(ReturnRegion,
1026 Nullability::Contradicted);
1027 C.addTransition(State);
1028 return;
1029 }
1030 }
1031 }
1032 }
1033
1034 const ObjCMessageExpr *Message = M.getOriginExpr();
1035 Nullability SelfNullability = getReceiverNullability(M, State);
1036
1037 const NullabilityState *NullabilityOfReturn =
1038 State->get<NullabilityMap>(ReturnRegion);
1039
1040 if (NullabilityOfReturn) {
1041 // When we have a nullability tracked for the return value, the nullability
1042 // of the expression will be the most nullable of the receiver and the
1043 // return value.
1044 Nullability RetValTracked = NullabilityOfReturn->getValue();
1045 Nullability ComputedNullab =
1046 getMostNullable(RetValTracked, SelfNullability);
1047 if (ComputedNullab != RetValTracked &&
1048 ComputedNullab != Nullability::Unspecified) {
1049 const Stmt *NullabilitySource =
1050 ComputedNullab == RetValTracked
1051 ? NullabilityOfReturn->getNullabilitySource()
1052 : Message->getInstanceReceiver();
1053 State = State->set<NullabilityMap>(
1054 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1055 C.addTransition(State);
1056 }
1057 return;
1058 }
1059
1060 // No tracked information. Use static type information for return value.
1061 Nullability RetNullability = getNullabilityAnnotation(Message->getType());
1062
1063 // Properties might be computed, which means the property value could
1064 // theoretically change between calls even in commonly-observed cases like
1065 // this:
1066 //
1067 // if (foo.prop) { // ok, it's nonnull here...
1068 // [bar doStuffWithNonnullVal:foo.prop]; // ...but what about
1069 // here?
1070 // }
1071 //
1072 // If the property is nullable-annotated, a naive analysis would lead to many
1073 // false positives despite the presence of probably-correct nil-checks. To
1074 // reduce the false positive rate, we maintain a history of the most recently
1075 // observed property value. For each property access, if the prior value has
1076 // been constrained to be not nil then we will conservatively assume that the
1077 // next access can be inferred as nonnull.
1078 if (RetNullability != Nullability::Nonnull &&
1079 M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined) {
1080 bool LookupResolved = false;
1081 if (const MemRegion *ReceiverRegion = getTrackRegion(M.getReceiverSVal())) {
1082 if (const IdentifierInfo *Ident =
1084 LookupResolved = true;
1085 ObjectPropPair Key = std::make_pair(ReceiverRegion, Ident);
1086 const ConstrainedPropertyVal *PrevPropVal =
1087 State->get<PropertyAccessesMap>(Key);
1088 if (PrevPropVal && PrevPropVal->isConstrainedNonnull) {
1089 RetNullability = Nullability::Nonnull;
1090 } else {
1091 // If a previous property access was constrained as nonnull, we hold
1092 // on to that constraint (effectively inferring that all subsequent
1093 // accesses on that code path can be inferred as nonnull). If the
1094 // previous property access was *not* constrained as nonnull, then
1095 // let's throw it away in favor of keeping the SVal associated with
1096 // this more recent access.
1097 if (auto ReturnSVal =
1098 M.getReturnValue().getAs<DefinedOrUnknownSVal>()) {
1099 State = State->set<PropertyAccessesMap>(
1100 Key, ConstrainedPropertyVal(*ReturnSVal));
1101 }
1102 }
1103 }
1104 }
1105
1106 if (!LookupResolved) {
1107 // Fallback: err on the side of suppressing the false positive.
1108 RetNullability = Nullability::Nonnull;
1109 }
1110 }
1111
1112 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
1113 if (ComputedNullab == Nullability::Nullable) {
1114 const Stmt *NullabilitySource = ComputedNullab == RetNullability
1115 ? Message
1116 : Message->getInstanceReceiver();
1117 State = State->set<NullabilityMap>(
1118 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
1119 C.addTransition(State);
1120 }
1121}
1122
1123/// Explicit casts are trusted. If there is a disagreement in the nullability
1124/// annotations in the destination and the source or '0' is casted to nonnull
1125/// track the value as having contraditory nullability. This will allow users to
1126/// suppress warnings.
1127void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
1128 CheckerContext &C) const {
1129 QualType OriginType = CE->getSubExpr()->getType();
1130 QualType DestType = CE->getType();
1131 if (!isValidPointerType(OriginType))
1132 return;
1133 if (!isValidPointerType(DestType))
1134 return;
1135
1136 ProgramStateRef State = C.getState();
1137 if (State->get<InvariantViolated>())
1138 return;
1139
1140 Nullability DestNullability = getNullabilityAnnotation(DestType);
1141
1142 // No explicit nullability in the destination type, so this cast does not
1143 // change the nullability.
1144 if (DestNullability == Nullability::Unspecified)
1145 return;
1146
1147 auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
1148 const MemRegion *Region = getTrackRegion(*RegionSVal);
1149 if (!Region)
1150 return;
1151
1152 // When 0 is converted to nonnull mark it as contradicted.
1153 if (DestNullability == Nullability::Nonnull) {
1154 NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
1155 if (Nullness == NullConstraint::IsNull) {
1156 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1157 C.addTransition(State);
1158 return;
1159 }
1160 }
1161
1162 const NullabilityState *TrackedNullability =
1163 State->get<NullabilityMap>(Region);
1164
1165 if (!TrackedNullability) {
1166 if (DestNullability != Nullability::Nullable)
1167 return;
1168 State = State->set<NullabilityMap>(Region,
1169 NullabilityState(DestNullability, CE));
1170 C.addTransition(State);
1171 return;
1172 }
1173
1174 if (TrackedNullability->getValue() != DestNullability &&
1175 TrackedNullability->getValue() != Nullability::Contradicted) {
1176 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
1177 C.addTransition(State);
1178 }
1179}
1180
1181/// For a given statement performing a bind, attempt to syntactically
1182/// match the expression resulting in the bound value.
1183static const Expr * matchValueExprForBind(const Stmt *S) {
1184 // For `x = e` the value expression is the right-hand side.
1185 if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
1186 if (BinOp->getOpcode() == BO_Assign)
1187 return BinOp->getRHS();
1188 }
1189
1190 // For `int x = e` the value expression is the initializer.
1191 if (auto *DS = dyn_cast<DeclStmt>(S)) {
1192 if (DS->isSingleDecl()) {
1193 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1194 if (!VD)
1195 return nullptr;
1196
1197 if (const Expr *Init = VD->getInit())
1198 return Init;
1199 }
1200 }
1201
1202 return nullptr;
1203}
1204
1205/// Returns true if \param S is a DeclStmt for a local variable that
1206/// ObjC automated reference counting initialized with zero.
1208 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1209 // prevents false positives when a _Nonnull local variable cannot be
1210 // initialized with an initialization expression:
1211 // NSString * _Nonnull s; // no-warning
1212 // @autoreleasepool {
1213 // s = ...
1214 // }
1215 //
1216 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1217 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1218 // the zero-initialized definition will unexpectedly yield nil.
1219
1220 // Locals are only zero-initialized when automated reference counting
1221 // is turned on.
1222 if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
1223 return false;
1224
1225 auto *DS = dyn_cast<DeclStmt>(S);
1226 if (!DS || !DS->isSingleDecl())
1227 return false;
1228
1229 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1230 if (!VD)
1231 return false;
1232
1233 // Sema only zero-initializes locals with ObjCLifetimes.
1234 if(!VD->getType().getQualifiers().hasObjCLifetime())
1235 return false;
1236
1237 const Expr *Init = VD->getInit();
1238 assert(Init && "ObjC local under ARC without initializer");
1239
1240 // Return false if the local is explicitly initialized (e.g., with '= nil').
1242 return false;
1243
1244 return true;
1245}
1246
1247/// Propagate the nullability information through binds and warn when nullable
1248/// pointer or null symbol is assigned to a pointer with a nonnull type.
1249void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
1250 bool AtDeclInit, CheckerContext &C) const {
1251 const TypedValueRegion *TVR =
1252 dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
1253 if (!TVR)
1254 return;
1255
1256 QualType LocType = TVR->getValueType();
1257 if (!isValidPointerType(LocType))
1258 return;
1259
1260 ProgramStateRef State = C.getState();
1261 if (State->get<InvariantViolated>())
1262 return;
1263
1264 auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1265 if (!ValDefOrUnknown)
1266 return;
1267
1268 NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1269
1270 Nullability ValNullability = Nullability::Unspecified;
1271 if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1272 ValNullability = getNullabilityAnnotation(Sym->getType());
1273
1274 Nullability LocNullability = getNullabilityAnnotation(LocType);
1275
1276 // If the type of the RHS expression is nonnull, don't warn. This
1277 // enables explicit suppression with a cast to nonnull.
1278 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1279 const Expr *ValueExpr = matchValueExprForBind(S);
1280 if (ValueExpr) {
1281 ValueExprTypeLevelNullability =
1283 }
1284
1285 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1286 RhsNullness == NullConstraint::IsNull);
1287 if (NullPassedToNonnull.isEnabled() && NullAssignedToNonNull &&
1288 ValNullability != Nullability::Nonnull &&
1289 ValueExprTypeLevelNullability != Nullability::Nonnull &&
1291 ExplodedNode *N = C.generateErrorNode(State);
1292 if (!N)
1293 return;
1294
1295
1296 const Stmt *ValueStmt = S;
1297 if (ValueExpr)
1298 ValueStmt = ValueExpr;
1299
1300 SmallString<256> SBuf;
1301 llvm::raw_svector_ostream OS(SBuf);
1302 OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
1303 OS << " assigned to a pointer which is expected to have non-null value";
1304 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
1305 NullPassedToNonnull, N, nullptr, C, ValueStmt);
1306 return;
1307 }
1308
1309 // If null was returned from a non-null function, mark the nullability
1310 // invariant as violated even if the diagnostic was suppressed.
1311 if (NullAssignedToNonNull) {
1312 State = State->set<InvariantViolated>(true);
1313 C.addTransition(State);
1314 return;
1315 }
1316
1317 // Intentionally missing case: '0' is bound to a reference. It is handled by
1318 // the DereferenceChecker.
1319
1320 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1321 if (!ValueRegion)
1322 return;
1323
1324 const NullabilityState *TrackedNullability =
1325 State->get<NullabilityMap>(ValueRegion);
1326
1327 if (TrackedNullability) {
1328 if (RhsNullness == NullConstraint::IsNotNull ||
1329 TrackedNullability->getValue() != Nullability::Nullable)
1330 return;
1331 if (NullablePassedToNonnull.isEnabled() &&
1332 LocNullability == Nullability::Nonnull) {
1333 ExplodedNode *N = C.addTransition(State, C.getPredecessor());
1334 reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1335 "which is expected to have non-null value",
1336 ErrorKind::NullableAssignedToNonnull,
1337 NullablePassedToNonnull, N, ValueRegion, C);
1338 }
1339 return;
1340 }
1341
1342 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1343
1344 if (ValNullability == Nullability::Nullable) {
1345 // Trust the static information of the value more than the static
1346 // information on the location.
1347 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1348 State = State->set<NullabilityMap>(
1349 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1350 C.addTransition(State);
1351 return;
1352 }
1353
1354 if (LocNullability == Nullability::Nullable) {
1355 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1356 State = State->set<NullabilityMap>(
1357 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1358 C.addTransition(State);
1359 }
1360}
1361
1362void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1363 const char *NL, const char *Sep) const {
1364
1365 NullabilityMapTy B = State->get<NullabilityMap>();
1366
1367 if (State->get<InvariantViolated>())
1368 Out << Sep << NL
1369 << "Nullability invariant was violated, warnings suppressed." << NL;
1370
1371 if (B.isEmpty())
1372 return;
1373
1374 if (!State->get<InvariantViolated>())
1375 Out << Sep << NL;
1376
1377 for (auto [Region, State] : B) {
1378 Out << Region << " : ";
1379 State.print(Out);
1380 Out << NL;
1381 }
1382}
1383
1384// The checker group "nullability" (which consists of the checkers that are
1385// implemented in this file) has a group-level configuration option which
1386// affects all the checkers in the group. As this is a completely unique
1387// remnant of old design (this is the only group option in the analyzer), there
1388// is no machinery to inject the group name from `Checkers.td`, so it is simply
1389// hardcoded here:
1390constexpr llvm::StringLiteral GroupName = "nullability";
1391constexpr llvm::StringLiteral GroupOptName = "NoDiagnoseCallsToSystemHeaders";
1392
1393#define REGISTER_CHECKER(NAME, TRACKING_REQUIRED) \
1394 void ento::register##NAME##Checker(CheckerManager &Mgr) { \
1395 NullabilityChecker *Chk = Mgr.getChecker<NullabilityChecker>(); \
1396 Chk->NAME.enable(Mgr); \
1397 Chk->NeedTracking = Chk->NeedTracking || TRACKING_REQUIRED; \
1398 Chk->NoDiagnoseCallsToSystemHeaders = \
1399 Mgr.getAnalyzerOptions().getCheckerBooleanOption(GroupName, \
1400 GroupOptName, true); \
1401 } \
1402 \
1403 bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
1404 return true; \
1405 }
1406
1407// The checks are likely to be turned on by default and it is possible to do
1408// them without tracking any nullability related information. As an optimization
1409// no nullability information will be tracked when only these two checks are
1410// enables.
1411REGISTER_CHECKER(NullPassedToNonnull, false)
1412REGISTER_CHECKER(NullReturnedFromNonnull, false)
1413
1414REGISTER_CHECKER(NullableDereferenced, true)
1415REGISTER_CHECKER(NullablePassedToNonnull, true)
1416REGISTER_CHECKER(NullableReturnedFromNonnull, true)
1417
1418#undef REGISTER_CHECKER
#define V(N, I)
#define REGISTER_CHECKER(name)
TokenType getType() const
Returns the token's type, e.g.
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
#define X(type, name)
Definition Value.h:97
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 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.
static bool checkParamsForPreconditionViolation(ArrayRef< ParmVarDecl * > Params, ProgramStateRef State, const StackFrame *SF)
static bool checkSelfIvarsForInvariantViolation(ProgramStateRef State, const StackFrame *SF)
static Nullability getReceiverNullability(const ObjCMethodCall &M, ProgramStateRef State)
#define SM(sm)
#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.
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:3729
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
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:3077
QualType getType() const
Definition Expr.h:144
QualType getReturnType() const
Definition TypeBase.h:4905
Represents an ObjC class declaration.
Definition DeclObjC.h:1154
Represents a pointer to an Objective C object.
Definition TypeBase.h:8063
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
Definition TypeBase.h:8115
A (possibly-)qualified type.
Definition TypeBase.h:937
Expr * getRetValue()
Definition Stmt.h:3197
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.
It represents a stack frame of the call stack.
const Decl * getDecl() const
const ImplicitParamDecl * getSelfDecl() const
Stmt - This represents one statement.
Definition Stmt.h:86
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isObjCObjectPointerType() const
Definition TypeBase.h:8861
QualType getType() const
Definition Decl.h:723
const SourceManager & getSourceManager() const
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
SVal getReturnValue() const
Returns the return value of the call.
Checker families (where a single backend class implements multiple related frontends) should derive f...
Definition Checker.h:581
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'.
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
const RegionTy * getAs() const
Definition MemRegion.h:1419
Represents any expression that calls an Objective-C method.
Definition CallEvent.h:1251
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Definition CallEvent.h:1280
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
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.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
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
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:806
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.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
Definition SymExpr.h:133
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool IsNonNull(InterpState &S, CodePtr OpPC)
Definition Interp.h:3107
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition CallGraph.h:206
Expr * Cond
};
ObjCMethodFamily
A family of Objective-C methods.
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:5973
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25