xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (revision b47128aaf37bc027d66a0bc331beaad4a84da4dd)
1 //== Nullabilityhecker.cpp - Nullability checker ----------------*- C++ -*--==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This checker tries to find nullability violations. There are several kinds of
11 // possible violations:
12 // * Null pointer is passed to a pointer which has a _Nonnull type.
13 // * Null pointer is returned from a function which has a _Nonnull return type.
14 // * Nullable pointer is passed to a pointer which has a _Nonnull type.
15 // * Nullable pointer is returned from a function which has a _Nonnull return
16 //   type.
17 // * Nullable pointer is dereferenced.
18 //
19 // This checker propagates the nullability information of the pointers and looks
20 // for the patterns that are described above. Explicit casts are trusted and are
21 // considered a way to suppress false positives for this checker. The other way
22 // to suppress warnings would be to add asserts or guarding if statements to the
23 // code. In addition to the nullability propagation this checker also uses some
24 // heuristics to suppress potential false positives.
25 //
26 //===----------------------------------------------------------------------===//
27 
28 #include "ClangSACheckers.h"
29 #include "llvm/Support/Path.h"
30 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
31 #include "clang/StaticAnalyzer/Core/Checker.h"
32 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
33 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
34 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
35 
36 using namespace clang;
37 using namespace ento;
38 
39 namespace {
40 // Do not reorder! The getMostNullable method relies on the order.
41 // Optimization: Most pointers expected to be unspecified. When a symbol has an
42 // unspecified or nonnull type non of the rules would indicate any problem for
43 // that symbol. For this reason only nullable and contradicted nullability are
44 // stored for a symbol. When a symbol is already contradicted, it can not be
45 // casted back to nullable.
46 enum class Nullability : char {
47   Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
48                 // not report any nullability related issue for this symbol.
49                 // This nullability is propagated agressively to avoid false
50                 // positive results. See the comment on getMostNullable method.
51   Nullable,
52   Unspecified,
53   Nonnull
54 };
55 
56 /// Returns the most nullable nullability. This is used for message expressions
57 /// like [reciever method], where the nullability of this expression is either
58 /// the nullability of the receiver or the nullability of the return type of the
59 /// method, depending on which is more nullable. Contradicted is considered to
60 /// be the most nullable, to avoid false positive results.
61 static Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
62   return static_cast<Nullability>(
63       std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
64 }
65 
66 static const char *getNullabilityString(Nullability Nullab) {
67   switch (Nullab) {
68   case Nullability::Contradicted:
69     return "contradicted";
70   case Nullability::Nullable:
71     return "nullable";
72   case Nullability::Unspecified:
73     return "unspecified";
74   case Nullability::Nonnull:
75     return "nonnull";
76   }
77   assert(false);
78   return "";
79 }
80 
81 // These enums are used as an index to ErrorMessages array.
82 enum class ErrorKind : int {
83   NilAssignedToNonnull,
84   NilPassedToNonnull,
85   NilReturnedToNonnull,
86   NullableAssignedToNonnull,
87   NullableReturnedToNonnull,
88   NullableDereferenced,
89   NullablePassedToNonnull
90 };
91 
92 const char *ErrorMessages[] = {"Null pointer is assigned to a pointer which "
93                                "has _Nonnull type",
94                                "Null pointer is passed to a parameter which is "
95                                "marked as _Nonnull",
96                                "Null pointer is returned from a function that "
97                                "has _Nonnull return type",
98                                "Nullable pointer is assigned to a pointer "
99                                "which has _Nonnull type",
100                                "Nullable pointer is returned from a function "
101                                "that has _Nonnull return type",
102                                "Nullable pointer is dereferenced",
103                                "Nullable pointer is passed to a parameter "
104                                "which is marked as _Nonnull"};
105 
106 class NullabilityChecker
107     : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
108                      check::PostCall, check::PostStmt<ExplicitCastExpr>,
109                      check::PostObjCMessage, check::DeadSymbols,
110                      check::Event<ImplicitNullDerefEvent>> {
111   mutable std::unique_ptr<BugType> BT;
112 
113 public:
114   void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
115   void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
116   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
117   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
118   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
119   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
120   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
121   void checkEvent(ImplicitNullDerefEvent Event) const;
122 
123   void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
124                   const char *Sep) const override;
125 
126   struct NullabilityChecksFilter {
127     DefaultBool CheckNullPassedToNonnull;
128     DefaultBool CheckNullReturnedFromNonnull;
129     DefaultBool CheckNullableDereferenced;
130     DefaultBool CheckNullablePassedToNonnull;
131     DefaultBool CheckNullableReturnedFromNonnull;
132 
133     CheckName CheckNameNullPassedToNonnull;
134     CheckName CheckNameNullReturnedFromNonnull;
135     CheckName CheckNameNullableDereferenced;
136     CheckName CheckNameNullablePassedToNonnull;
137     CheckName CheckNameNullableReturnedFromNonnull;
138   };
139 
140   NullabilityChecksFilter Filter;
141 
142 private:
143   class NullabilityBugVisitor
144       : public BugReporterVisitorImpl<NullabilityBugVisitor> {
145   public:
146     NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
147 
148     void Profile(llvm::FoldingSetNodeID &ID) const override {
149       static int X = 0;
150       ID.AddPointer(&X);
151       ID.AddPointer(Region);
152     }
153 
154     PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
155                                    const ExplodedNode *PrevN,
156                                    BugReporterContext &BRC,
157                                    BugReport &BR) override;
158 
159   private:
160     // The tracked region.
161     const MemRegion *Region;
162   };
163 
164   /// When any of the nonnull arguments of the analyzed function is null, do not
165   /// report anything and turn off the check.
166   ///
167   /// When \p SuppressPath is set to true, no more bugs will be reported on this
168   /// path by this checker.
169   void reportBugIfPreconditionHolds(ErrorKind Error, ExplodedNode *N,
170                                     const MemRegion *Region, CheckerContext &C,
171                                     const Stmt *ValueExpr = nullptr,
172                                     bool SuppressPath = false) const;
173 
174   void reportBug(ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
175                  BugReporter &BR, const Stmt *ValueExpr = nullptr) const {
176     if (!BT)
177       BT.reset(new BugType(this, "Nullability", "Memory error"));
178     const char *Msg = ErrorMessages[static_cast<int>(Error)];
179     assert(Msg);
180     std::unique_ptr<BugReport> R(new BugReport(*BT, Msg, N));
181     if (Region) {
182       R->markInteresting(Region);
183       R->addVisitor(llvm::make_unique<NullabilityBugVisitor>(Region));
184     }
185     if (ValueExpr) {
186       R->addRange(ValueExpr->getSourceRange());
187       if (Error == ErrorKind::NilAssignedToNonnull ||
188           Error == ErrorKind::NilPassedToNonnull ||
189           Error == ErrorKind::NilReturnedToNonnull)
190         bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
191     }
192     BR.emitReport(std::move(R));
193   }
194 };
195 
196 class NullabilityState {
197 public:
198   NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
199       : Nullab(Nullab), Source(Source) {}
200 
201   const Stmt *getNullabilitySource() const { return Source; }
202 
203   Nullability getValue() const { return Nullab; }
204 
205   void Profile(llvm::FoldingSetNodeID &ID) const {
206     ID.AddInteger(static_cast<char>(Nullab));
207     ID.AddPointer(Source);
208   }
209 
210   void print(raw_ostream &Out) const {
211     Out << getNullabilityString(Nullab) << "\n";
212   }
213 
214 private:
215   Nullability Nullab;
216   // Source is the expression which determined the nullability. For example in a
217   // message like [nullable nonnull_returning] has nullable nullability, because
218   // the receiver is nullable. Here the receiver will be the source of the
219   // nullability. This is useful information when the diagnostics are generated.
220   const Stmt *Source;
221 };
222 
223 bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
224   return Lhs.getValue() == Rhs.getValue() &&
225          Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
226 }
227 
228 } // end anonymous namespace
229 
230 REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
231                                NullabilityState)
232 
233 // If the nullability precondition of a function is violated, we should not
234 // report nullability related issues on that path. For this reason once a
235 // precondition is not met on a path, this checker will be esentially turned off
236 // for the rest of the analysis. We do not want to generate a sink node however,
237 // so this checker would not lead to reduced coverage.
238 REGISTER_TRAIT_WITH_PROGRAMSTATE(PreconditionViolated, bool)
239 
240 enum class NullConstraint { IsNull, IsNotNull, Unknown };
241 
242 static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
243                                         ProgramStateRef State) {
244   ConditionTruthVal Nullness = State->isNull(Val);
245   if (Nullness.isConstrainedFalse())
246     return NullConstraint::IsNotNull;
247   if (Nullness.isConstrainedTrue())
248     return NullConstraint::IsNull;
249   return NullConstraint::Unknown;
250 }
251 
252 // If an SVal wraps a region that should be tracked, it will return a pointer
253 // to the wrapped region. Otherwise it will return a nullptr.
254 static const SymbolicRegion *getTrackRegion(SVal Val,
255                                             bool CheckSuperRegion = false) {
256   auto RegionSVal = Val.getAs<loc::MemRegionVal>();
257   if (!RegionSVal)
258     return nullptr;
259 
260   const MemRegion *Region = RegionSVal->getRegion();
261 
262   if (CheckSuperRegion) {
263     if (auto FieldReg = Region->getAs<FieldRegion>())
264       return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
265     else if (auto ElementReg = Region->getAs<ElementRegion>())
266       return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
267   }
268 
269   return dyn_cast<SymbolicRegion>(Region);
270 }
271 
272 PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
273     const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
274     BugReport &BR) {
275   ProgramStateRef state = N->getState();
276   ProgramStateRef statePrev = PrevN->getState();
277 
278   const NullabilityState *TrackedNullab = state->get<NullabilityMap>(Region);
279   const NullabilityState *TrackedNullabPrev =
280       statePrev->get<NullabilityMap>(Region);
281   if (!TrackedNullab)
282     return nullptr;
283 
284   if (TrackedNullabPrev &&
285       TrackedNullabPrev->getValue() == TrackedNullab->getValue())
286     return nullptr;
287 
288   // Retrieve the associated statement.
289   const Stmt *S = TrackedNullab->getNullabilitySource();
290   if (!S) {
291     ProgramPoint ProgLoc = N->getLocation();
292     if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
293       S = SP->getStmt();
294     }
295   }
296 
297   if (!S)
298     return nullptr;
299 
300   std::string InfoText =
301       (llvm::Twine("Nullability '") +
302        getNullabilityString(TrackedNullab->getValue()) + "' is infered")
303           .str();
304 
305   // Generate the extra diagnostic.
306   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
307                              N->getLocationContext());
308   return new PathDiagnosticEventPiece(Pos, InfoText, true, nullptr);
309 }
310 
311 static Nullability getNullabilityAnnotation(QualType Type) {
312   const auto *AttrType = Type->getAs<AttributedType>();
313   if (!AttrType)
314     return Nullability::Unspecified;
315   if (AttrType->getAttrKind() == AttributedType::attr_nullable)
316     return Nullability::Nullable;
317   else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
318     return Nullability::Nonnull;
319   return Nullability::Unspecified;
320 }
321 
322 template <typename ParamVarDeclRange>
323 static bool
324 checkParamsForPreconditionViolation(const ParamVarDeclRange &Params,
325                                     ProgramStateRef State,
326                                     const LocationContext *LocCtxt) {
327   for (const auto *ParamDecl : Params) {
328     if (ParamDecl->isParameterPack())
329       break;
330 
331     if (getNullabilityAnnotation(ParamDecl->getType()) != Nullability::Nonnull)
332       continue;
333 
334     auto RegVal = State->getLValue(ParamDecl, LocCtxt)
335                       .template getAs<loc::MemRegionVal>();
336     if (!RegVal)
337       continue;
338 
339     auto ParamValue = State->getSVal(RegVal->getRegion())
340                           .template getAs<DefinedOrUnknownSVal>();
341     if (!ParamValue)
342       continue;
343 
344     if (getNullConstraint(*ParamValue, State) == NullConstraint::IsNull) {
345       return true;
346     }
347   }
348   return false;
349 }
350 
351 static bool checkPreconditionViolation(ProgramStateRef State, ExplodedNode *N,
352                                        CheckerContext &C) {
353   if (State->get<PreconditionViolated>())
354     return true;
355 
356   const LocationContext *LocCtxt = C.getLocationContext();
357   const Decl *D = LocCtxt->getDecl();
358   if (!D)
359     return false;
360 
361   if (const auto *BlockD = dyn_cast<BlockDecl>(D)) {
362     if (checkParamsForPreconditionViolation(BlockD->parameters(), State,
363                                             LocCtxt)) {
364       if (!N->isSink())
365         C.addTransition(State->set<PreconditionViolated>(true), N);
366       return true;
367     }
368     return false;
369   }
370 
371   if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
372     if (checkParamsForPreconditionViolation(FuncDecl->parameters(), State,
373                                             LocCtxt)) {
374       if (!N->isSink())
375         C.addTransition(State->set<PreconditionViolated>(true), N);
376       return true;
377     }
378     return false;
379   }
380   return false;
381 }
382 
383 void NullabilityChecker::reportBugIfPreconditionHolds(
384     ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
385     CheckerContext &C, const Stmt *ValueExpr, bool SuppressPath) const {
386   ProgramStateRef OriginalState = N->getState();
387 
388   if (checkPreconditionViolation(OriginalState, N, C))
389     return;
390   if (SuppressPath) {
391     OriginalState = OriginalState->set<PreconditionViolated>(true);
392     N = C.addTransition(OriginalState, N);
393   }
394 
395   reportBug(Error, N, Region, C.getBugReporter(), ValueExpr);
396 }
397 
398 /// Cleaning up the program state.
399 void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
400                                           CheckerContext &C) const {
401   ProgramStateRef State = C.getState();
402   NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
403   for (NullabilityMapTy::iterator I = Nullabilities.begin(),
404                                   E = Nullabilities.end();
405        I != E; ++I) {
406     if (!SR.isLiveRegion(I->first)) {
407       State = State->remove<NullabilityMap>(I->first);
408     }
409   }
410   // When one of the nonnull arguments are constrained to be null, nullability
411   // preconditions are violated. It is not enough to check this only when we
412   // actually report an error, because at that time interesting symbols might be
413   // reaped.
414   if (checkPreconditionViolation(State, C.getPredecessor(), C))
415     return;
416   C.addTransition(State);
417 }
418 
419 /// This callback triggers when a pointer is dereferenced and the analyzer does
420 /// not know anything about the value of that pointer. When that pointer is
421 /// nullable, this code emits a warning.
422 void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
423   if (Event.SinkNode->getState()->get<PreconditionViolated>())
424     return;
425 
426   const MemRegion *Region =
427       getTrackRegion(Event.Location, /*CheckSuperregion=*/true);
428   if (!Region)
429     return;
430 
431   ProgramStateRef State = Event.SinkNode->getState();
432   const NullabilityState *TrackedNullability =
433       State->get<NullabilityMap>(Region);
434 
435   if (!TrackedNullability)
436     return;
437 
438   if (Filter.CheckNullableDereferenced &&
439       TrackedNullability->getValue() == Nullability::Nullable) {
440     BugReporter &BR = *Event.BR;
441     // Do not suppress errors on defensive code paths, because dereferencing
442     // a nullable pointer is always an error.
443     if (Event.IsDirectDereference)
444       reportBug(ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
445     else
446       reportBug(ErrorKind::NullablePassedToNonnull, Event.SinkNode, Region, BR);
447   }
448 }
449 
450 /// This method check when nullable pointer or null value is returned from a
451 /// function that has nonnull return type.
452 ///
453 /// TODO: when nullability preconditons are violated, it is ok to violate the
454 /// nullability postconditons (i.e.: when one of the nonnull parameters are null
455 /// this check should not report any nullability related issue).
456 void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
457                                       CheckerContext &C) const {
458   auto RetExpr = S->getRetValue();
459   if (!RetExpr)
460     return;
461 
462   if (!RetExpr->getType()->isAnyPointerType())
463     return;
464 
465   ProgramStateRef State = C.getState();
466   if (State->get<PreconditionViolated>())
467     return;
468 
469   auto RetSVal =
470       State->getSVal(S, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
471   if (!RetSVal)
472     return;
473 
474   AnalysisDeclContext *DeclCtxt =
475       C.getLocationContext()->getAnalysisDeclContext();
476   const FunctionType *FuncType = DeclCtxt->getDecl()->getFunctionType();
477   if (!FuncType)
478     return;
479 
480   NullConstraint Nullness = getNullConstraint(*RetSVal, State);
481 
482   Nullability StaticNullability =
483       getNullabilityAnnotation(FuncType->getReturnType());
484 
485   if (Filter.CheckNullReturnedFromNonnull &&
486       Nullness == NullConstraint::IsNull &&
487       StaticNullability == Nullability::Nonnull) {
488     static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
489     ExplodedNode *N = C.generateSink(State, C.getPredecessor(), &Tag);
490     reportBugIfPreconditionHolds(ErrorKind::NilReturnedToNonnull, N, nullptr, C,
491                                  RetExpr);
492     return;
493   }
494 
495   const MemRegion *Region = getTrackRegion(*RetSVal);
496   if (!Region)
497     return;
498 
499   const NullabilityState *TrackedNullability =
500       State->get<NullabilityMap>(Region);
501   if (TrackedNullability) {
502     Nullability TrackedNullabValue = TrackedNullability->getValue();
503     if (Filter.CheckNullableReturnedFromNonnull &&
504         Nullness != NullConstraint::IsNotNull &&
505         TrackedNullabValue == Nullability::Nullable &&
506         StaticNullability == Nullability::Nonnull) {
507       static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
508       ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
509       reportBugIfPreconditionHolds(ErrorKind::NullableReturnedToNonnull, N,
510                                    Region, C);
511     }
512     return;
513   }
514   if (StaticNullability == Nullability::Nullable) {
515     State = State->set<NullabilityMap>(Region,
516                                        NullabilityState(StaticNullability, S));
517     C.addTransition(State);
518   }
519 }
520 
521 /// This callback warns when a nullable pointer or a null value is passed to a
522 /// function that expects its argument to be nonnull.
523 void NullabilityChecker::checkPreCall(const CallEvent &Call,
524                                       CheckerContext &C) const {
525   if (!Call.getDecl())
526     return;
527 
528   ProgramStateRef State = C.getState();
529   if (State->get<PreconditionViolated>())
530     return;
531 
532   ProgramStateRef OrigState = State;
533 
534   unsigned Idx = 0;
535   for (const ParmVarDecl *Param : Call.parameters()) {
536     if (Param->isParameterPack())
537       break;
538 
539     const Expr *ArgExpr = nullptr;
540     if (Idx < Call.getNumArgs())
541       ArgExpr = Call.getArgExpr(Idx);
542     auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
543     if (!ArgSVal)
544       continue;
545 
546     if (!Param->getType()->isAnyPointerType() &&
547         !Param->getType()->isReferenceType())
548       continue;
549 
550     NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
551 
552     Nullability ParamNullability = getNullabilityAnnotation(Param->getType());
553     Nullability ArgStaticNullability =
554         getNullabilityAnnotation(ArgExpr->getType());
555 
556     if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
557         ArgStaticNullability != Nullability::Nonnull &&
558         ParamNullability == Nullability::Nonnull) {
559       ExplodedNode *N = C.generateSink(State);
560       reportBugIfPreconditionHolds(ErrorKind::NilPassedToNonnull, N, nullptr, C,
561                                    ArgExpr);
562       return;
563     }
564 
565     const MemRegion *Region = getTrackRegion(*ArgSVal);
566     if (!Region)
567       continue;
568 
569     const NullabilityState *TrackedNullability =
570         State->get<NullabilityMap>(Region);
571 
572     if (TrackedNullability) {
573       if (Nullness == NullConstraint::IsNotNull ||
574           TrackedNullability->getValue() != Nullability::Nullable)
575         continue;
576 
577       if (Filter.CheckNullablePassedToNonnull &&
578           ParamNullability == Nullability::Nonnull) {
579         ExplodedNode *N = C.addTransition(State);
580         reportBugIfPreconditionHolds(ErrorKind::NullablePassedToNonnull, N,
581                                      Region, C, ArgExpr, /*SuppressPath=*/true);
582         return;
583       }
584       if (Filter.CheckNullableDereferenced &&
585           Param->getType()->isReferenceType()) {
586         ExplodedNode *N = C.addTransition(State);
587         reportBugIfPreconditionHolds(ErrorKind::NullableDereferenced, N, Region,
588                                      C, ArgExpr, /*SuppressPath=*/true);
589         return;
590       }
591       continue;
592     }
593     // No tracked nullability yet.
594     if (ArgStaticNullability != Nullability::Nullable)
595       continue;
596     State = State->set<NullabilityMap>(
597         Region, NullabilityState(ArgStaticNullability, ArgExpr));
598   }
599   if (State != OrigState)
600     C.addTransition(State);
601 }
602 
603 /// Suppress the nullability warnings for some functions.
604 void NullabilityChecker::checkPostCall(const CallEvent &Call,
605                                        CheckerContext &C) const {
606   auto Decl = Call.getDecl();
607   if (!Decl)
608     return;
609   // ObjC Messages handles in a different callback.
610   if (Call.getKind() == CE_ObjCMessage)
611     return;
612   const FunctionType *FuncType = Decl->getFunctionType();
613   if (!FuncType)
614     return;
615   QualType ReturnType = FuncType->getReturnType();
616   if (!ReturnType->isAnyPointerType())
617     return;
618   ProgramStateRef State = C.getState();
619   if (State->get<PreconditionViolated>())
620     return;
621 
622   const MemRegion *Region = getTrackRegion(Call.getReturnValue());
623   if (!Region)
624     return;
625 
626   // CG headers are misannotated. Do not warn for symbols that are the results
627   // of CG calls.
628   const SourceManager &SM = C.getSourceManager();
629   StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
630   if (llvm::sys::path::filename(FilePath).startswith("CG")) {
631     State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
632     C.addTransition(State);
633     return;
634   }
635 
636   const NullabilityState *TrackedNullability =
637       State->get<NullabilityMap>(Region);
638 
639   if (!TrackedNullability &&
640       getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
641     State = State->set<NullabilityMap>(Region, Nullability::Nullable);
642     C.addTransition(State);
643   }
644 }
645 
646 static Nullability getReceiverNullability(const ObjCMethodCall &M,
647                                           ProgramStateRef State) {
648   Nullability RetNullability = Nullability::Unspecified;
649   if (M.isReceiverSelfOrSuper()) {
650     // For super and super class receivers we assume that the receiver is
651     // nonnull.
652     RetNullability = Nullability::Nonnull;
653   } else {
654     // Otherwise look up nullability in the state.
655     SVal Receiver = M.getReceiverSVal();
656     auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
657     if (ValueRegionSVal) {
658       const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
659       assert(SelfRegion);
660 
661       const NullabilityState *TrackedSelfNullability =
662           State->get<NullabilityMap>(SelfRegion);
663       if (TrackedSelfNullability) {
664         RetNullability = TrackedSelfNullability->getValue();
665       }
666     }
667     if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
668       // If the receiver is constrained to be nonnull, assume that it is nonnull
669       // regardless of its type.
670       NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
671       if (Nullness == NullConstraint::IsNotNull)
672         RetNullability = Nullability::Nonnull;
673     }
674   }
675   return RetNullability;
676 }
677 
678 /// Calculate the nullability of the result of a message expr based on the
679 /// nullability of the receiver, the nullability of the return value, and the
680 /// constraints.
681 void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
682                                               CheckerContext &C) const {
683   auto Decl = M.getDecl();
684   if (!Decl)
685     return;
686   QualType RetType = Decl->getReturnType();
687   if (!RetType->isAnyPointerType())
688     return;
689 
690   ProgramStateRef State = C.getState();
691   if (State->get<PreconditionViolated>())
692     return;
693 
694   const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
695   if (!ReturnRegion)
696     return;
697 
698   auto Interface = Decl->getClassInterface();
699   auto Name = Interface ? Interface->getName() : "";
700   // In order to reduce the noise in the diagnostics generated by this checker,
701   // some framework and programming style based heuristics are used. These
702   // heuristics are for Cocoa APIs which have NS prefix.
703   if (Name.startswith("NS")) {
704     // Developers rely on dynamic invariants such as an item should be available
705     // in a collection, or a collection is not empty often. Those invariants can
706     // not be inferred by any static analysis tool. To not to bother the users
707     // with too many false positives, every item retrieval function should be
708     // ignored for collections. The instance methods of dictionaries in Cocoa
709     // are either item retrieval related or not interesting nullability wise.
710     // Using this fact, to keep the code easier to read just ignore the return
711     // value of every instance method of dictionaries.
712     if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
713       State =
714           State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
715       C.addTransition(State);
716       return;
717     }
718     // For similar reasons ignore some methods of Cocoa arrays.
719     StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
720     if (Name.find("Array") != StringRef::npos &&
721         (FirstSelectorSlot == "firstObject" ||
722          FirstSelectorSlot == "lastObject")) {
723       State =
724           State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
725       C.addTransition(State);
726       return;
727     }
728 
729     // Encoding related methods of string should not fail when lossless
730     // encodings are used. Using lossless encodings is so frequent that ignoring
731     // this class of methods reduced the emitted diagnostics by about 30% on
732     // some projects (and all of that was false positives).
733     if (Name.find("String") != StringRef::npos) {
734       for (auto Param : M.parameters()) {
735         if (Param->getName() == "encoding") {
736           State = State->set<NullabilityMap>(ReturnRegion,
737                                              Nullability::Contradicted);
738           C.addTransition(State);
739           return;
740         }
741       }
742     }
743   }
744 
745   const ObjCMessageExpr *Message = M.getOriginExpr();
746   Nullability SelfNullability = getReceiverNullability(M, State);
747 
748   const NullabilityState *NullabilityOfReturn =
749       State->get<NullabilityMap>(ReturnRegion);
750 
751   if (NullabilityOfReturn) {
752     // When we have a nullability tracked for the return value, the nullability
753     // of the expression will be the most nullable of the receiver and the
754     // return value.
755     Nullability RetValTracked = NullabilityOfReturn->getValue();
756     Nullability ComputedNullab =
757         getMostNullable(RetValTracked, SelfNullability);
758     if (ComputedNullab != RetValTracked &&
759         ComputedNullab != Nullability::Unspecified) {
760       const Stmt *NullabilitySource =
761           ComputedNullab == RetValTracked
762               ? NullabilityOfReturn->getNullabilitySource()
763               : Message->getInstanceReceiver();
764       State = State->set<NullabilityMap>(
765           ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
766       C.addTransition(State);
767     }
768     return;
769   }
770 
771   // No tracked information. Use static type information for return value.
772   Nullability RetNullability = getNullabilityAnnotation(RetType);
773 
774   // Properties might be computed. For this reason the static analyzer creates a
775   // new symbol each time an unknown property  is read. To avoid false pozitives
776   // do not treat unknown properties as nullable, even when they explicitly
777   // marked nullable.
778   if (M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined)
779     RetNullability = Nullability::Nonnull;
780 
781   Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
782   if (ComputedNullab == Nullability::Nullable) {
783     const Stmt *NullabilitySource = ComputedNullab == RetNullability
784                                         ? Message
785                                         : Message->getInstanceReceiver();
786     State = State->set<NullabilityMap>(
787         ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
788     C.addTransition(State);
789   }
790 }
791 
792 /// Explicit casts are trusted. If there is a disagreement in the nullability
793 /// annotations in the destination and the source or '0' is casted to nonnull
794 /// track the value as having contraditory nullability. This will allow users to
795 /// suppress warnings.
796 void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
797                                        CheckerContext &C) const {
798   QualType OriginType = CE->getSubExpr()->getType();
799   QualType DestType = CE->getType();
800   if (!OriginType->isAnyPointerType())
801     return;
802   if (!DestType->isAnyPointerType())
803     return;
804 
805   ProgramStateRef State = C.getState();
806   if (State->get<PreconditionViolated>())
807     return;
808 
809   Nullability DestNullability = getNullabilityAnnotation(DestType);
810 
811   // No explicit nullability in the destination type, so this cast does not
812   // change the nullability.
813   if (DestNullability == Nullability::Unspecified)
814     return;
815 
816   auto RegionSVal =
817       State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
818   const MemRegion *Region = getTrackRegion(*RegionSVal);
819   if (!Region)
820     return;
821 
822   // When 0 is converted to nonnull mark it as contradicted.
823   if (DestNullability == Nullability::Nonnull) {
824     NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
825     if (Nullness == NullConstraint::IsNull) {
826       State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
827       C.addTransition(State);
828       return;
829     }
830   }
831 
832   const NullabilityState *TrackedNullability =
833       State->get<NullabilityMap>(Region);
834 
835   if (!TrackedNullability) {
836     if (DestNullability != Nullability::Nullable)
837       return;
838     State = State->set<NullabilityMap>(Region,
839                                        NullabilityState(DestNullability, CE));
840     C.addTransition(State);
841     return;
842   }
843 
844   if (TrackedNullability->getValue() != DestNullability &&
845       TrackedNullability->getValue() != Nullability::Contradicted) {
846     State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
847     C.addTransition(State);
848   }
849 }
850 
851 /// Propagate the nullability information through binds and warn when nullable
852 /// pointer or null symbol is assigned to a pointer with a nonnull type.
853 void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
854                                    CheckerContext &C) const {
855   const TypedValueRegion *TVR =
856       dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
857   if (!TVR)
858     return;
859 
860   QualType LocType = TVR->getValueType();
861   if (!LocType->isAnyPointerType())
862     return;
863 
864   ProgramStateRef State = C.getState();
865   if (State->get<PreconditionViolated>())
866     return;
867 
868   auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
869   if (!ValDefOrUnknown)
870     return;
871 
872   NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
873 
874   Nullability ValNullability = Nullability::Unspecified;
875   if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
876     ValNullability = getNullabilityAnnotation(Sym->getType());
877 
878   Nullability LocNullability = getNullabilityAnnotation(LocType);
879   if (Filter.CheckNullPassedToNonnull &&
880       RhsNullness == NullConstraint::IsNull &&
881       ValNullability != Nullability::Nonnull &&
882       LocNullability == Nullability::Nonnull) {
883     static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
884     ExplodedNode *N = C.generateSink(State, C.getPredecessor(), &Tag);
885     reportBugIfPreconditionHolds(ErrorKind::NilAssignedToNonnull, N, nullptr, C,
886                                  S);
887     return;
888   }
889   // Intentionally missing case: '0' is bound to a reference. It is handled by
890   // the DereferenceChecker.
891 
892   const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
893   if (!ValueRegion)
894     return;
895 
896   const NullabilityState *TrackedNullability =
897       State->get<NullabilityMap>(ValueRegion);
898 
899   if (TrackedNullability) {
900     if (RhsNullness == NullConstraint::IsNotNull ||
901         TrackedNullability->getValue() != Nullability::Nullable)
902       return;
903     if (Filter.CheckNullablePassedToNonnull &&
904         LocNullability == Nullability::Nonnull) {
905       static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
906       ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
907       reportBugIfPreconditionHolds(ErrorKind::NullableAssignedToNonnull, N,
908                                    ValueRegion, C);
909     }
910     return;
911   }
912 
913   const auto *BinOp = dyn_cast<BinaryOperator>(S);
914 
915   if (ValNullability == Nullability::Nullable) {
916     // Trust the static information of the value more than the static
917     // information on the location.
918     const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
919     State = State->set<NullabilityMap>(
920         ValueRegion, NullabilityState(ValNullability, NullabilitySource));
921     C.addTransition(State);
922     return;
923   }
924 
925   if (LocNullability == Nullability::Nullable) {
926     const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
927     State = State->set<NullabilityMap>(
928         ValueRegion, NullabilityState(LocNullability, NullabilitySource));
929     C.addTransition(State);
930   }
931 }
932 
933 void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
934                                     const char *NL, const char *Sep) const {
935 
936   NullabilityMapTy B = State->get<NullabilityMap>();
937 
938   if (B.isEmpty())
939     return;
940 
941   Out << Sep << NL;
942 
943   for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
944     Out << I->first << " : ";
945     I->second.print(Out);
946     Out << NL;
947   }
948 }
949 
950 #define REGISTER_CHECKER(name)                                                 \
951   void ento::register##name##Checker(CheckerManager &mgr) {                    \
952     NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>();   \
953     checker->Filter.Check##name = true;                                        \
954     checker->Filter.CheckName##name = mgr.getCurrentCheckName();               \
955   }
956 
957 REGISTER_CHECKER(NullPassedToNonnull)
958 REGISTER_CHECKER(NullReturnedFromNonnull)
959 REGISTER_CHECKER(NullableDereferenced)
960 REGISTER_CHECKER(NullablePassedToNonnull)
961 REGISTER_CHECKER(NullableReturnedFromNonnull)
962