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