blob: ad68dc2f49db66167a805dec597895fc37b4c56b [file] [log] [blame]
Gabor Horvath28690922015-08-26 23:17:43 +00001//== 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"
Anna Zaksad9e7ea2016-01-29 18:43:15 +000029
Gabor Horvath28690922015-08-26 23:17:43 +000030#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
31#include "clang/StaticAnalyzer/Core/Checker.h"
32#include "clang/StaticAnalyzer/Core/CheckerManager.h"
George Karpenkov2301c5a2018-03-23 00:16:03 +000033#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
Gabor Horvath28690922015-08-26 23:17:43 +000034#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
36
Anna Zaksad9e7ea2016-01-29 18:43:15 +000037#include "llvm/ADT/StringExtras.h"
38#include "llvm/Support/Path.h"
39
Gabor Horvath28690922015-08-26 23:17:43 +000040using namespace clang;
41using namespace ento;
42
43namespace {
Gabor Horvath28690922015-08-26 23:17:43 +000044
45/// Returns the most nullable nullability. This is used for message expressions
Simon Pilgrim2c518802017-03-30 14:13:19 +000046/// like [receiver method], where the nullability of this expression is either
Gabor Horvath28690922015-08-26 23:17:43 +000047/// the nullability of the receiver or the nullability of the return type of the
48/// method, depending on which is more nullable. Contradicted is considered to
49/// be the most nullable, to avoid false positive results.
Gabor Horvath3943adb2015-09-11 16:29:05 +000050Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
Gabor Horvath28690922015-08-26 23:17:43 +000051 return static_cast<Nullability>(
52 std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
53}
54
Gabor Horvath3943adb2015-09-11 16:29:05 +000055const char *getNullabilityString(Nullability Nullab) {
Gabor Horvath28690922015-08-26 23:17:43 +000056 switch (Nullab) {
57 case Nullability::Contradicted:
58 return "contradicted";
59 case Nullability::Nullable:
60 return "nullable";
61 case Nullability::Unspecified:
62 return "unspecified";
63 case Nullability::Nonnull:
64 return "nonnull";
65 }
Gabor Horvath3943adb2015-09-11 16:29:05 +000066 llvm_unreachable("Unexpected enumeration.");
Gabor Horvath28690922015-08-26 23:17:43 +000067 return "";
68}
69
70// These enums are used as an index to ErrorMessages array.
71enum class ErrorKind : int {
72 NilAssignedToNonnull,
73 NilPassedToNonnull,
74 NilReturnedToNonnull,
75 NullableAssignedToNonnull,
76 NullableReturnedToNonnull,
77 NullableDereferenced,
78 NullablePassedToNonnull
79};
80
Gabor Horvath28690922015-08-26 23:17:43 +000081class NullabilityChecker
82 : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
83 check::PostCall, check::PostStmt<ExplicitCastExpr>,
84 check::PostObjCMessage, check::DeadSymbols,
85 check::Event<ImplicitNullDerefEvent>> {
86 mutable std::unique_ptr<BugType> BT;
87
88public:
Devin Coughlina1d9d752016-03-05 01:32:43 +000089 // If true, the checker will not diagnose nullabilility issues for calls
90 // to system headers. This option is motivated by the observation that large
91 // projects may have many nullability warnings. These projects may
92 // find warnings about nullability annotations that they have explicitly
93 // added themselves higher priority to fix than warnings on calls to system
94 // libraries.
95 DefaultBool NoDiagnoseCallsToSystemHeaders;
96
Gabor Horvath28690922015-08-26 23:17:43 +000097 void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
98 void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
99 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
100 void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
101 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
102 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
103 void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
104 void checkEvent(ImplicitNullDerefEvent Event) const;
105
106 void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
107 const char *Sep) const override;
108
109 struct NullabilityChecksFilter {
110 DefaultBool CheckNullPassedToNonnull;
111 DefaultBool CheckNullReturnedFromNonnull;
112 DefaultBool CheckNullableDereferenced;
113 DefaultBool CheckNullablePassedToNonnull;
114 DefaultBool CheckNullableReturnedFromNonnull;
115
116 CheckName CheckNameNullPassedToNonnull;
117 CheckName CheckNameNullReturnedFromNonnull;
118 CheckName CheckNameNullableDereferenced;
119 CheckName CheckNameNullablePassedToNonnull;
120 CheckName CheckNameNullableReturnedFromNonnull;
121 };
122
123 NullabilityChecksFilter Filter;
Gabor Horvath29307352015-09-14 18:31:34 +0000124 // When set to false no nullability information will be tracked in
125 // NullabilityMap. It is possible to catch errors like passing a null pointer
126 // to a callee that expects nonnull argument without the information that is
127 // stroed in the NullabilityMap. This is an optimization.
128 DefaultBool NeedTracking;
Gabor Horvath28690922015-08-26 23:17:43 +0000129
130private:
George Karpenkov70ec1dd2018-06-26 21:12:08 +0000131 class NullabilityBugVisitor : public BugReporterVisitor {
Gabor Horvath28690922015-08-26 23:17:43 +0000132 public:
133 NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
134
135 void Profile(llvm::FoldingSetNodeID &ID) const override {
136 static int X = 0;
137 ID.AddPointer(&X);
138 ID.AddPointer(Region);
139 }
140
David Blaikie0a0c2752017-01-05 17:26:53 +0000141 std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
David Blaikie0a0c2752017-01-05 17:26:53 +0000142 BugReporterContext &BRC,
143 BugReport &BR) override;
Gabor Horvath28690922015-08-26 23:17:43 +0000144
145 private:
146 // The tracked region.
147 const MemRegion *Region;
148 };
149
Gabor Horvathb47128a2015-09-03 23:16:21 +0000150 /// When any of the nonnull arguments of the analyzed function is null, do not
151 /// report anything and turn off the check.
152 ///
153 /// When \p SuppressPath is set to true, no more bugs will be reported on this
154 /// path by this checker.
Devin Coughlin77942db2016-03-28 20:30:25 +0000155 void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error,
156 ExplodedNode *N, const MemRegion *Region,
157 CheckerContext &C,
158 const Stmt *ValueExpr = nullptr,
159 bool SuppressPath = false) const;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000160
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000161 void reportBug(StringRef Msg, ErrorKind Error, ExplodedNode *N,
162 const MemRegion *Region, BugReporter &BR,
163 const Stmt *ValueExpr = nullptr) const {
Gabor Horvath28690922015-08-26 23:17:43 +0000164 if (!BT)
Artem Dergachevb6a513d2017-05-03 11:47:13 +0000165 BT.reset(new BugType(this, "Nullability", categories::MemoryError));
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000166
167 auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
Gabor Horvath28690922015-08-26 23:17:43 +0000168 if (Region) {
169 R->markInteresting(Region);
170 R->addVisitor(llvm::make_unique<NullabilityBugVisitor>(Region));
171 }
172 if (ValueExpr) {
173 R->addRange(ValueExpr->getSourceRange());
174 if (Error == ErrorKind::NilAssignedToNonnull ||
175 Error == ErrorKind::NilPassedToNonnull ||
176 Error == ErrorKind::NilReturnedToNonnull)
George Karpenkovb2cf0062018-10-23 18:24:53 +0000177 if (const auto *Ex = dyn_cast<Expr>(ValueExpr))
178 bugreporter::trackExpressionValue(N, Ex, *R);
Gabor Horvath28690922015-08-26 23:17:43 +0000179 }
180 BR.emitReport(std::move(R));
181 }
Gabor Horvath29307352015-09-14 18:31:34 +0000182
183 /// If an SVal wraps a region that should be tracked, it will return a pointer
184 /// to the wrapped region. Otherwise it will return a nullptr.
185 const SymbolicRegion *getTrackRegion(SVal Val,
186 bool CheckSuperRegion = false) const;
Devin Coughlina1d9d752016-03-05 01:32:43 +0000187
188 /// Returns true if the call is diagnosable in the currrent analyzer
189 /// configuration.
190 bool isDiagnosableCall(const CallEvent &Call) const {
191 if (NoDiagnoseCallsToSystemHeaders && Call.isInSystemHeader())
192 return false;
193
194 return true;
195 }
Gabor Horvath28690922015-08-26 23:17:43 +0000196};
197
198class NullabilityState {
199public:
200 NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
201 : Nullab(Nullab), Source(Source) {}
202
203 const Stmt *getNullabilitySource() const { return Source; }
204
205 Nullability getValue() const { return Nullab; }
206
207 void Profile(llvm::FoldingSetNodeID &ID) const {
208 ID.AddInteger(static_cast<char>(Nullab));
209 ID.AddPointer(Source);
210 }
211
212 void print(raw_ostream &Out) const {
213 Out << getNullabilityString(Nullab) << "\n";
214 }
215
216private:
217 Nullability Nullab;
218 // Source is the expression which determined the nullability. For example in a
219 // message like [nullable nonnull_returning] has nullable nullability, because
220 // the receiver is nullable. Here the receiver will be the source of the
221 // nullability. This is useful information when the diagnostics are generated.
222 const Stmt *Source;
223};
224
225bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
226 return Lhs.getValue() == Rhs.getValue() &&
227 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
228}
229
230} // end anonymous namespace
231
232REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
233 NullabilityState)
234
Devin Coughlin77942db2016-03-28 20:30:25 +0000235// We say "the nullability type invariant is violated" when a location with a
236// non-null type contains NULL or a function with a non-null return type returns
237// NULL. Violations of the nullability type invariant can be detected either
238// directly (for example, when NULL is passed as an argument to a nonnull
239// parameter) or indirectly (for example, when, inside a function, the
240// programmer defensively checks whether a nonnull parameter contains NULL and
241// finds that it does).
242//
243// As a matter of policy, the nullability checker typically warns on direct
244// violations of the nullability invariant (although it uses various
245// heuristics to suppress warnings in some cases) but will not warn if the
246// invariant has already been violated along the path (either directly or
247// indirectly). As a practical matter, this prevents the analyzer from
248// (1) warning on defensive code paths where a nullability precondition is
249// determined to have been violated, (2) warning additional times after an
250// initial direct violation has been discovered, and (3) warning after a direct
251// violation that has been implicitly or explicitly suppressed (for
252// example, with a cast of NULL to _Nonnull). In essence, once an invariant
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +0000253// violation is detected on a path, this checker will be essentially turned off
Devin Coughlin77942db2016-03-28 20:30:25 +0000254// for the rest of the analysis
255//
256// The analyzer takes this approach (rather than generating a sink node) to
257// ensure coverage of defensive paths, which may be important for backwards
258// compatibility in codebases that were developed without nullability in mind.
259REGISTER_TRAIT_WITH_PROGRAMSTATE(InvariantViolated, bool)
Gabor Horvathb47128a2015-09-03 23:16:21 +0000260
Gabor Horvath28690922015-08-26 23:17:43 +0000261enum class NullConstraint { IsNull, IsNotNull, Unknown };
262
263static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
264 ProgramStateRef State) {
265 ConditionTruthVal Nullness = State->isNull(Val);
266 if (Nullness.isConstrainedFalse())
267 return NullConstraint::IsNotNull;
268 if (Nullness.isConstrainedTrue())
269 return NullConstraint::IsNull;
270 return NullConstraint::Unknown;
271}
272
Gabor Horvath29307352015-09-14 18:31:34 +0000273const SymbolicRegion *
274NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
275 if (!NeedTracking)
276 return nullptr;
277
Gabor Horvath28690922015-08-26 23:17:43 +0000278 auto RegionSVal = Val.getAs<loc::MemRegionVal>();
279 if (!RegionSVal)
280 return nullptr;
281
282 const MemRegion *Region = RegionSVal->getRegion();
283
284 if (CheckSuperRegion) {
285 if (auto FieldReg = Region->getAs<FieldRegion>())
286 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
Gabor Horvath3943adb2015-09-11 16:29:05 +0000287 if (auto ElementReg = Region->getAs<ElementRegion>())
Gabor Horvath28690922015-08-26 23:17:43 +0000288 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
289 }
290
291 return dyn_cast<SymbolicRegion>(Region);
292}
293
David Blaikie0a0c2752017-01-05 17:26:53 +0000294std::shared_ptr<PathDiagnosticPiece>
295NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
David Blaikie0a0c2752017-01-05 17:26:53 +0000296 BugReporterContext &BRC,
297 BugReport &BR) {
Gabor Horvath3943adb2015-09-11 16:29:05 +0000298 ProgramStateRef State = N->getState();
George Karpenkovc82d4572018-09-28 18:49:41 +0000299 ProgramStateRef StatePrev = N->getFirstPred()->getState();
Gabor Horvath28690922015-08-26 23:17:43 +0000300
Gabor Horvath3943adb2015-09-11 16:29:05 +0000301 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
Gabor Horvath28690922015-08-26 23:17:43 +0000302 const NullabilityState *TrackedNullabPrev =
Gabor Horvath3943adb2015-09-11 16:29:05 +0000303 StatePrev->get<NullabilityMap>(Region);
Gabor Horvath28690922015-08-26 23:17:43 +0000304 if (!TrackedNullab)
305 return nullptr;
306
307 if (TrackedNullabPrev &&
308 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
309 return nullptr;
310
311 // Retrieve the associated statement.
312 const Stmt *S = TrackedNullab->getNullabilitySource();
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000313 if (!S || S->getBeginLoc().isInvalid()) {
Gabor Horvath6ee4f902016-08-18 07:54:50 +0000314 S = PathDiagnosticLocation::getStmt(N);
Gabor Horvath28690922015-08-26 23:17:43 +0000315 }
316
317 if (!S)
318 return nullptr;
319
320 std::string InfoText =
321 (llvm::Twine("Nullability '") +
Devin Coughlinc894ac82016-12-07 17:36:27 +0000322 getNullabilityString(TrackedNullab->getValue()) + "' is inferred")
Gabor Horvath28690922015-08-26 23:17:43 +0000323 .str();
324
325 // Generate the extra diagnostic.
326 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
327 N->getLocationContext());
David Blaikie0a0c2752017-01-05 17:26:53 +0000328 return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true,
329 nullptr);
Gabor Horvath28690922015-08-26 23:17:43 +0000330}
331
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000332/// Returns true when the value stored at the given location is null
333/// and the passed in type is nonnnull.
334static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
335 SVal LV, QualType T) {
336 if (getNullabilityAnnotation(T) != Nullability::Nonnull)
337 return false;
338
339 auto RegionVal = LV.getAs<loc::MemRegionVal>();
340 if (!RegionVal)
341 return false;
342
343 auto StoredVal =
344 State->getSVal(RegionVal->getRegion()).getAs<DefinedOrUnknownSVal>();
345 if (!StoredVal)
346 return false;
347
348 if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
349 return true;
350
351 return false;
352}
353
Gabor Horvathb47128a2015-09-03 23:16:21 +0000354static bool
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000355checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl *> Params,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000356 ProgramStateRef State,
357 const LocationContext *LocCtxt) {
358 for (const auto *ParamDecl : Params) {
359 if (ParamDecl->isParameterPack())
360 break;
361
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000362 SVal LV = State->getLValue(ParamDecl, LocCtxt);
363 if (checkValueAtLValForInvariantViolation(State, LV,
364 ParamDecl->getType())) {
365 return true;
366 }
367 }
368 return false;
369}
Gabor Horvathb47128a2015-09-03 23:16:21 +0000370
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000371static bool
372checkSelfIvarsForInvariantViolation(ProgramStateRef State,
373 const LocationContext *LocCtxt) {
374 auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->getDecl());
375 if (!MD || !MD->isInstanceMethod())
376 return false;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000377
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000378 const ImplicitParamDecl *SelfDecl = LocCtxt->getSelfDecl();
379 if (!SelfDecl)
380 return false;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000381
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000382 SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
383
384 const ObjCObjectPointerType *SelfType =
385 dyn_cast<ObjCObjectPointerType>(SelfDecl->getType());
386 if (!SelfType)
387 return false;
388
389 const ObjCInterfaceDecl *ID = SelfType->getInterfaceDecl();
390 if (!ID)
391 return false;
392
393 for (const auto *IvarDecl : ID->ivars()) {
394 SVal LV = State->getLValue(IvarDecl, SelfVal);
395 if (checkValueAtLValForInvariantViolation(State, LV, IvarDecl->getType())) {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000396 return true;
397 }
398 }
399 return false;
400}
401
Devin Coughlin77942db2016-03-28 20:30:25 +0000402static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
403 CheckerContext &C) {
404 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000405 return true;
406
407 const LocationContext *LocCtxt = C.getLocationContext();
408 const Decl *D = LocCtxt->getDecl();
409 if (!D)
410 return false;
411
Devin Coughlin851da712016-01-15 21:35:40 +0000412 ArrayRef<ParmVarDecl*> Params;
413 if (const auto *BD = dyn_cast<BlockDecl>(D))
414 Params = BD->parameters();
415 else if (const auto *FD = dyn_cast<FunctionDecl>(D))
416 Params = FD->parameters();
417 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
418 Params = MD->parameters();
419 else
Gabor Horvathb47128a2015-09-03 23:16:21 +0000420 return false;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000421
Devin Coughlinb2d2a012016-04-13 00:41:54 +0000422 if (checkParamsForPreconditionViolation(Params, State, LocCtxt) ||
423 checkSelfIvarsForInvariantViolation(State, LocCtxt)) {
Devin Coughlin851da712016-01-15 21:35:40 +0000424 if (!N->isSink())
Devin Coughlin77942db2016-03-28 20:30:25 +0000425 C.addTransition(State->set<InvariantViolated>(true), N);
Devin Coughlin851da712016-01-15 21:35:40 +0000426 return true;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000427 }
428 return false;
429}
430
Devin Coughlin77942db2016-03-28 20:30:25 +0000431void NullabilityChecker::reportBugIfInvariantHolds(StringRef Msg,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000432 ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
433 CheckerContext &C, const Stmt *ValueExpr, bool SuppressPath) const {
434 ProgramStateRef OriginalState = N->getState();
435
Devin Coughlin77942db2016-03-28 20:30:25 +0000436 if (checkInvariantViolation(OriginalState, N, C))
Gabor Horvathb47128a2015-09-03 23:16:21 +0000437 return;
438 if (SuppressPath) {
Devin Coughlin77942db2016-03-28 20:30:25 +0000439 OriginalState = OriginalState->set<InvariantViolated>(true);
Gabor Horvathb47128a2015-09-03 23:16:21 +0000440 N = C.addTransition(OriginalState, N);
441 }
442
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000443 reportBug(Msg, Error, N, Region, C.getBugReporter(), ValueExpr);
Gabor Horvathb47128a2015-09-03 23:16:21 +0000444}
445
Gabor Horvath28690922015-08-26 23:17:43 +0000446/// Cleaning up the program state.
447void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
448 CheckerContext &C) const {
Gabor Horvathbe87d5b2015-09-14 20:31:46 +0000449 if (!SR.hasDeadSymbols())
450 return;
451
Gabor Horvath28690922015-08-26 23:17:43 +0000452 ProgramStateRef State = C.getState();
453 NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
454 for (NullabilityMapTy::iterator I = Nullabilities.begin(),
455 E = Nullabilities.end();
456 I != E; ++I) {
Gabor Horvathbe87d5b2015-09-14 20:31:46 +0000457 const auto *Region = I->first->getAs<SymbolicRegion>();
458 assert(Region && "Non-symbolic region is tracked.");
459 if (SR.isDead(Region->getSymbol())) {
Gabor Horvath28690922015-08-26 23:17:43 +0000460 State = State->remove<NullabilityMap>(I->first);
461 }
462 }
Gabor Horvathb47128a2015-09-03 23:16:21 +0000463 // When one of the nonnull arguments are constrained to be null, nullability
464 // preconditions are violated. It is not enough to check this only when we
465 // actually report an error, because at that time interesting symbols might be
466 // reaped.
Devin Coughlin77942db2016-03-28 20:30:25 +0000467 if (checkInvariantViolation(State, C.getPredecessor(), C))
Gabor Horvathb47128a2015-09-03 23:16:21 +0000468 return;
469 C.addTransition(State);
Gabor Horvath28690922015-08-26 23:17:43 +0000470}
471
472/// This callback triggers when a pointer is dereferenced and the analyzer does
473/// not know anything about the value of that pointer. When that pointer is
474/// nullable, this code emits a warning.
475void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
Devin Coughlin77942db2016-03-28 20:30:25 +0000476 if (Event.SinkNode->getState()->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000477 return;
478
Gabor Horvath28690922015-08-26 23:17:43 +0000479 const MemRegion *Region =
480 getTrackRegion(Event.Location, /*CheckSuperregion=*/true);
481 if (!Region)
482 return;
483
484 ProgramStateRef State = Event.SinkNode->getState();
485 const NullabilityState *TrackedNullability =
486 State->get<NullabilityMap>(Region);
487
488 if (!TrackedNullability)
489 return;
490
491 if (Filter.CheckNullableDereferenced &&
492 TrackedNullability->getValue() == Nullability::Nullable) {
493 BugReporter &BR = *Event.BR;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000494 // Do not suppress errors on defensive code paths, because dereferencing
495 // a nullable pointer is always an error.
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +0000496 if (Event.IsDirectDereference)
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000497 reportBug("Nullable pointer is dereferenced",
498 ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
499 else {
500 reportBug("Nullable pointer is passed to a callee that requires a "
501 "non-null", ErrorKind::NullablePassedToNonnull,
502 Event.SinkNode, Region, BR);
503 }
Gabor Horvath28690922015-08-26 23:17:43 +0000504 }
505}
506
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000507/// Find the outermost subexpression of E that is not an implicit cast.
508/// This looks through the implicit casts to _Nonnull that ARC adds to
509/// return expressions of ObjC types when the return type of the function or
510/// method is non-null but the express is not.
511static const Expr *lookThroughImplicitCasts(const Expr *E) {
512 assert(E);
513
514 while (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
515 E = ICE->getSubExpr();
516 }
517
518 return E;
519}
520
Gabor Horvath28690922015-08-26 23:17:43 +0000521/// This method check when nullable pointer or null value is returned from a
522/// function that has nonnull return type.
Gabor Horvath28690922015-08-26 23:17:43 +0000523void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
524 CheckerContext &C) const {
525 auto RetExpr = S->getRetValue();
526 if (!RetExpr)
527 return;
528
529 if (!RetExpr->getType()->isAnyPointerType())
530 return;
531
532 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +0000533 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000534 return;
535
George Karpenkovd703ec92018-01-17 20:27:29 +0000536 auto RetSVal = C.getSVal(S).getAs<DefinedOrUnknownSVal>();
Gabor Horvath28690922015-08-26 23:17:43 +0000537 if (!RetSVal)
538 return;
539
Devin Coughlinde217672016-01-28 22:23:34 +0000540 bool InSuppressedMethodFamily = false;
Devin Coughlin4a330202016-01-22 01:01:11 +0000541
Devin Coughlin851da712016-01-15 21:35:40 +0000542 QualType RequiredRetType;
Gabor Horvath28690922015-08-26 23:17:43 +0000543 AnalysisDeclContext *DeclCtxt =
544 C.getLocationContext()->getAnalysisDeclContext();
Devin Coughlin851da712016-01-15 21:35:40 +0000545 const Decl *D = DeclCtxt->getDecl();
Devin Coughlin4a330202016-01-22 01:01:11 +0000546 if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
Devin Coughlinde217672016-01-28 22:23:34 +0000547 // HACK: This is a big hammer to avoid warning when there are defensive
548 // nil checks in -init and -copy methods. We should add more sophisticated
549 // logic here to suppress on common defensive idioms but still
550 // warn when there is a likely problem.
551 ObjCMethodFamily Family = MD->getMethodFamily();
552 if (OMF_init == Family || OMF_copy == Family || OMF_mutableCopy == Family)
553 InSuppressedMethodFamily = true;
554
Devin Coughlin851da712016-01-15 21:35:40 +0000555 RequiredRetType = MD->getReturnType();
Devin Coughlin4a330202016-01-22 01:01:11 +0000556 } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
Devin Coughlin851da712016-01-15 21:35:40 +0000557 RequiredRetType = FD->getReturnType();
Devin Coughlin4a330202016-01-22 01:01:11 +0000558 } else {
Gabor Horvath28690922015-08-26 23:17:43 +0000559 return;
Devin Coughlin4a330202016-01-22 01:01:11 +0000560 }
Gabor Horvath28690922015-08-26 23:17:43 +0000561
562 NullConstraint Nullness = getNullConstraint(*RetSVal, State);
563
Devin Coughlin851da712016-01-15 21:35:40 +0000564 Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
Gabor Horvath28690922015-08-26 23:17:43 +0000565
Devin Coughlin755baa42015-12-29 17:40:49 +0000566 // If the returned value is null but the type of the expression
567 // generating it is nonnull then we will suppress the diagnostic.
568 // This enables explicit suppression when returning a nil literal in a
569 // function with a _Nonnull return type:
570 // return (NSString * _Nonnull)0;
571 Nullability RetExprTypeLevelNullability =
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000572 getNullabilityAnnotation(lookThroughImplicitCasts(RetExpr)->getType());
Devin Coughlin755baa42015-12-29 17:40:49 +0000573
Devin Coughlin77942db2016-03-28 20:30:25 +0000574 bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
575 Nullness == NullConstraint::IsNull);
Gabor Horvath28690922015-08-26 23:17:43 +0000576 if (Filter.CheckNullReturnedFromNonnull &&
Devin Coughlin77942db2016-03-28 20:30:25 +0000577 NullReturnedFromNonNull &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000578 RetExprTypeLevelNullability != Nullability::Nonnull &&
Devin Coughlin49bd58f2016-04-12 19:29:52 +0000579 !InSuppressedMethodFamily &&
580 C.getLocationContext()->inTopFrame()) {
Gabor Horvath28690922015-08-26 23:17:43 +0000581 static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
Devin Coughline39bd402015-09-16 22:03:05 +0000582 ExplodedNode *N = C.generateErrorNode(State, &Tag);
583 if (!N)
584 return;
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000585
586 SmallString<256> SBuf;
587 llvm::raw_svector_ostream OS(SBuf);
Anna Zaks6d4e76b2016-12-15 22:55:15 +0000588 OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
589 OS << " returned from a " << C.getDeclDescription(D) <<
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000590 " that is expected to return a non-null value";
Devin Coughlin77942db2016-03-28 20:30:25 +0000591 reportBugIfInvariantHolds(OS.str(),
592 ErrorKind::NilReturnedToNonnull, N, nullptr, C,
593 RetExpr);
594 return;
595 }
596
597 // If null was returned from a non-null function, mark the nullability
598 // invariant as violated even if the diagnostic was suppressed.
599 if (NullReturnedFromNonNull) {
600 State = State->set<InvariantViolated>(true);
601 C.addTransition(State);
Gabor Horvath28690922015-08-26 23:17:43 +0000602 return;
603 }
604
605 const MemRegion *Region = getTrackRegion(*RetSVal);
606 if (!Region)
607 return;
608
609 const NullabilityState *TrackedNullability =
610 State->get<NullabilityMap>(Region);
611 if (TrackedNullability) {
612 Nullability TrackedNullabValue = TrackedNullability->getValue();
613 if (Filter.CheckNullableReturnedFromNonnull &&
614 Nullness != NullConstraint::IsNotNull &&
615 TrackedNullabValue == Nullability::Nullable &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000616 RequiredNullability == Nullability::Nonnull) {
Gabor Horvath28690922015-08-26 23:17:43 +0000617 static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
618 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000619
620 SmallString<256> SBuf;
621 llvm::raw_svector_ostream OS(SBuf);
622 OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
623 " that is expected to return a non-null value";
624
Devin Coughlin77942db2016-03-28 20:30:25 +0000625 reportBugIfInvariantHolds(OS.str(),
626 ErrorKind::NullableReturnedToNonnull, N,
627 Region, C);
Gabor Horvath28690922015-08-26 23:17:43 +0000628 }
629 return;
630 }
Devin Coughlin755baa42015-12-29 17:40:49 +0000631 if (RequiredNullability == Nullability::Nullable) {
Gabor Horvath28690922015-08-26 23:17:43 +0000632 State = State->set<NullabilityMap>(Region,
Devin Coughlin755baa42015-12-29 17:40:49 +0000633 NullabilityState(RequiredNullability,
634 S));
Gabor Horvath28690922015-08-26 23:17:43 +0000635 C.addTransition(State);
636 }
637}
638
639/// This callback warns when a nullable pointer or a null value is passed to a
640/// function that expects its argument to be nonnull.
641void NullabilityChecker::checkPreCall(const CallEvent &Call,
642 CheckerContext &C) const {
643 if (!Call.getDecl())
644 return;
645
646 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +0000647 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000648 return;
649
Gabor Horvath28690922015-08-26 23:17:43 +0000650 ProgramStateRef OrigState = State;
651
652 unsigned Idx = 0;
653 for (const ParmVarDecl *Param : Call.parameters()) {
654 if (Param->isParameterPack())
655 break;
656
Devin Coughline4224cc2016-11-14 22:46:02 +0000657 if (Idx >= Call.getNumArgs())
658 break;
659
660 const Expr *ArgExpr = Call.getArgExpr(Idx);
Gabor Horvath28690922015-08-26 23:17:43 +0000661 auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
662 if (!ArgSVal)
663 continue;
664
665 if (!Param->getType()->isAnyPointerType() &&
666 !Param->getType()->isReferenceType())
667 continue;
668
669 NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
670
Devin Coughlin755baa42015-12-29 17:40:49 +0000671 Nullability RequiredNullability =
672 getNullabilityAnnotation(Param->getType());
673 Nullability ArgExprTypeLevelNullability =
Gabor Horvath28690922015-08-26 23:17:43 +0000674 getNullabilityAnnotation(ArgExpr->getType());
675
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000676 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
677
Gabor Horvath28690922015-08-26 23:17:43 +0000678 if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000679 ArgExprTypeLevelNullability != Nullability::Nonnull &&
Devin Coughlina1d9d752016-03-05 01:32:43 +0000680 RequiredNullability == Nullability::Nonnull &&
681 isDiagnosableCall(Call)) {
Devin Coughline39bd402015-09-16 22:03:05 +0000682 ExplodedNode *N = C.generateErrorNode(State);
683 if (!N)
684 return;
Anna Zaks6d4e76b2016-12-15 22:55:15 +0000685
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000686 SmallString<256> SBuf;
687 llvm::raw_svector_ostream OS(SBuf);
Anna Zaks6d4e76b2016-12-15 22:55:15 +0000688 OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
689 OS << " passed to a callee that requires a non-null " << ParamIdx
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000690 << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
Devin Coughlin77942db2016-03-28 20:30:25 +0000691 reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull, N,
692 nullptr, C,
693 ArgExpr, /*SuppressPath=*/false);
Gabor Horvath28690922015-08-26 23:17:43 +0000694 return;
695 }
696
697 const MemRegion *Region = getTrackRegion(*ArgSVal);
698 if (!Region)
699 continue;
700
701 const NullabilityState *TrackedNullability =
702 State->get<NullabilityMap>(Region);
703
704 if (TrackedNullability) {
705 if (Nullness == NullConstraint::IsNotNull ||
706 TrackedNullability->getValue() != Nullability::Nullable)
707 continue;
708
709 if (Filter.CheckNullablePassedToNonnull &&
Devin Coughlina1d9d752016-03-05 01:32:43 +0000710 RequiredNullability == Nullability::Nonnull &&
711 isDiagnosableCall(Call)) {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000712 ExplodedNode *N = C.addTransition(State);
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000713 SmallString<256> SBuf;
714 llvm::raw_svector_ostream OS(SBuf);
715 OS << "Nullable pointer is passed to a callee that requires a non-null "
716 << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
Devin Coughlin77942db2016-03-28 20:30:25 +0000717 reportBugIfInvariantHolds(OS.str(),
718 ErrorKind::NullablePassedToNonnull, N,
719 Region, C, ArgExpr, /*SuppressPath=*/true);
Gabor Horvath28690922015-08-26 23:17:43 +0000720 return;
721 }
722 if (Filter.CheckNullableDereferenced &&
723 Param->getType()->isReferenceType()) {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000724 ExplodedNode *N = C.addTransition(State);
Devin Coughlin77942db2016-03-28 20:30:25 +0000725 reportBugIfInvariantHolds("Nullable pointer is dereferenced",
726 ErrorKind::NullableDereferenced, N, Region,
727 C, ArgExpr, /*SuppressPath=*/true);
Gabor Horvath28690922015-08-26 23:17:43 +0000728 return;
729 }
730 continue;
731 }
732 // No tracked nullability yet.
Devin Coughlin755baa42015-12-29 17:40:49 +0000733 if (ArgExprTypeLevelNullability != Nullability::Nullable)
Gabor Horvath28690922015-08-26 23:17:43 +0000734 continue;
735 State = State->set<NullabilityMap>(
Devin Coughlin755baa42015-12-29 17:40:49 +0000736 Region, NullabilityState(ArgExprTypeLevelNullability, ArgExpr));
Gabor Horvath28690922015-08-26 23:17:43 +0000737 }
738 if (State != OrigState)
739 C.addTransition(State);
740}
741
742/// Suppress the nullability warnings for some functions.
743void NullabilityChecker::checkPostCall(const CallEvent &Call,
744 CheckerContext &C) const {
745 auto Decl = Call.getDecl();
746 if (!Decl)
747 return;
748 // ObjC Messages handles in a different callback.
749 if (Call.getKind() == CE_ObjCMessage)
750 return;
751 const FunctionType *FuncType = Decl->getFunctionType();
752 if (!FuncType)
753 return;
754 QualType ReturnType = FuncType->getReturnType();
755 if (!ReturnType->isAnyPointerType())
756 return;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000757 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +0000758 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000759 return;
760
Gabor Horvath28690922015-08-26 23:17:43 +0000761 const MemRegion *Region = getTrackRegion(Call.getReturnValue());
762 if (!Region)
763 return;
Gabor Horvath28690922015-08-26 23:17:43 +0000764
765 // CG headers are misannotated. Do not warn for symbols that are the results
766 // of CG calls.
767 const SourceManager &SM = C.getSourceManager();
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000768 StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
Gabor Horvath28690922015-08-26 23:17:43 +0000769 if (llvm::sys::path::filename(FilePath).startswith("CG")) {
770 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
771 C.addTransition(State);
772 return;
773 }
774
775 const NullabilityState *TrackedNullability =
776 State->get<NullabilityMap>(Region);
777
778 if (!TrackedNullability &&
779 getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
780 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
781 C.addTransition(State);
782 }
783}
784
785static Nullability getReceiverNullability(const ObjCMethodCall &M,
786 ProgramStateRef State) {
Gabor Horvath28690922015-08-26 23:17:43 +0000787 if (M.isReceiverSelfOrSuper()) {
788 // For super and super class receivers we assume that the receiver is
789 // nonnull.
Gabor Horvath3943adb2015-09-11 16:29:05 +0000790 return Nullability::Nonnull;
Gabor Horvath28690922015-08-26 23:17:43 +0000791 }
Gabor Horvath3943adb2015-09-11 16:29:05 +0000792 // Otherwise look up nullability in the state.
793 SVal Receiver = M.getReceiverSVal();
794 if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
795 // If the receiver is constrained to be nonnull, assume that it is nonnull
796 // regardless of its type.
797 NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
798 if (Nullness == NullConstraint::IsNotNull)
799 return Nullability::Nonnull;
800 }
801 auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
802 if (ValueRegionSVal) {
803 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
804 assert(SelfRegion);
805
806 const NullabilityState *TrackedSelfNullability =
807 State->get<NullabilityMap>(SelfRegion);
808 if (TrackedSelfNullability)
809 return TrackedSelfNullability->getValue();
810 }
811 return Nullability::Unspecified;
Gabor Horvath28690922015-08-26 23:17:43 +0000812}
813
814/// Calculate the nullability of the result of a message expr based on the
815/// nullability of the receiver, the nullability of the return value, and the
816/// constraints.
817void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
818 CheckerContext &C) const {
819 auto Decl = M.getDecl();
820 if (!Decl)
821 return;
822 QualType RetType = Decl->getReturnType();
823 if (!RetType->isAnyPointerType())
824 return;
825
Gabor Horvathb47128a2015-09-03 23:16:21 +0000826 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +0000827 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000828 return;
829
Gabor Horvath28690922015-08-26 23:17:43 +0000830 const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
831 if (!ReturnRegion)
832 return;
833
Gabor Horvath28690922015-08-26 23:17:43 +0000834 auto Interface = Decl->getClassInterface();
835 auto Name = Interface ? Interface->getName() : "";
836 // In order to reduce the noise in the diagnostics generated by this checker,
837 // some framework and programming style based heuristics are used. These
838 // heuristics are for Cocoa APIs which have NS prefix.
839 if (Name.startswith("NS")) {
840 // Developers rely on dynamic invariants such as an item should be available
841 // in a collection, or a collection is not empty often. Those invariants can
842 // not be inferred by any static analysis tool. To not to bother the users
843 // with too many false positives, every item retrieval function should be
844 // ignored for collections. The instance methods of dictionaries in Cocoa
845 // are either item retrieval related or not interesting nullability wise.
846 // Using this fact, to keep the code easier to read just ignore the return
847 // value of every instance method of dictionaries.
George Karpenkov2301c5a2018-03-23 00:16:03 +0000848 if (M.isInstanceMessage() && Name.contains("Dictionary")) {
Gabor Horvath28690922015-08-26 23:17:43 +0000849 State =
850 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
851 C.addTransition(State);
852 return;
853 }
854 // For similar reasons ignore some methods of Cocoa arrays.
855 StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
George Karpenkov2301c5a2018-03-23 00:16:03 +0000856 if (Name.contains("Array") &&
Gabor Horvath28690922015-08-26 23:17:43 +0000857 (FirstSelectorSlot == "firstObject" ||
858 FirstSelectorSlot == "lastObject")) {
859 State =
860 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
861 C.addTransition(State);
862 return;
863 }
864
865 // Encoding related methods of string should not fail when lossless
866 // encodings are used. Using lossless encodings is so frequent that ignoring
867 // this class of methods reduced the emitted diagnostics by about 30% on
868 // some projects (and all of that was false positives).
George Karpenkov2301c5a2018-03-23 00:16:03 +0000869 if (Name.contains("String")) {
Gabor Horvath28690922015-08-26 23:17:43 +0000870 for (auto Param : M.parameters()) {
871 if (Param->getName() == "encoding") {
872 State = State->set<NullabilityMap>(ReturnRegion,
873 Nullability::Contradicted);
874 C.addTransition(State);
875 return;
876 }
877 }
878 }
879 }
880
881 const ObjCMessageExpr *Message = M.getOriginExpr();
882 Nullability SelfNullability = getReceiverNullability(M, State);
883
884 const NullabilityState *NullabilityOfReturn =
885 State->get<NullabilityMap>(ReturnRegion);
886
887 if (NullabilityOfReturn) {
888 // When we have a nullability tracked for the return value, the nullability
889 // of the expression will be the most nullable of the receiver and the
890 // return value.
891 Nullability RetValTracked = NullabilityOfReturn->getValue();
892 Nullability ComputedNullab =
893 getMostNullable(RetValTracked, SelfNullability);
894 if (ComputedNullab != RetValTracked &&
895 ComputedNullab != Nullability::Unspecified) {
896 const Stmt *NullabilitySource =
897 ComputedNullab == RetValTracked
898 ? NullabilityOfReturn->getNullabilitySource()
899 : Message->getInstanceReceiver();
900 State = State->set<NullabilityMap>(
901 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
902 C.addTransition(State);
903 }
904 return;
905 }
906
907 // No tracked information. Use static type information for return value.
908 Nullability RetNullability = getNullabilityAnnotation(RetType);
909
910 // Properties might be computed. For this reason the static analyzer creates a
911 // new symbol each time an unknown property is read. To avoid false pozitives
912 // do not treat unknown properties as nullable, even when they explicitly
913 // marked nullable.
914 if (M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined)
915 RetNullability = Nullability::Nonnull;
916
917 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
918 if (ComputedNullab == Nullability::Nullable) {
919 const Stmt *NullabilitySource = ComputedNullab == RetNullability
920 ? Message
921 : Message->getInstanceReceiver();
922 State = State->set<NullabilityMap>(
923 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
924 C.addTransition(State);
925 }
926}
927
928/// Explicit casts are trusted. If there is a disagreement in the nullability
929/// annotations in the destination and the source or '0' is casted to nonnull
930/// track the value as having contraditory nullability. This will allow users to
931/// suppress warnings.
932void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
933 CheckerContext &C) const {
934 QualType OriginType = CE->getSubExpr()->getType();
935 QualType DestType = CE->getType();
936 if (!OriginType->isAnyPointerType())
937 return;
938 if (!DestType->isAnyPointerType())
939 return;
940
Gabor Horvathb47128a2015-09-03 23:16:21 +0000941 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +0000942 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +0000943 return;
944
Gabor Horvath28690922015-08-26 23:17:43 +0000945 Nullability DestNullability = getNullabilityAnnotation(DestType);
946
947 // No explicit nullability in the destination type, so this cast does not
948 // change the nullability.
949 if (DestNullability == Nullability::Unspecified)
950 return;
951
George Karpenkovd703ec92018-01-17 20:27:29 +0000952 auto RegionSVal = C.getSVal(CE).getAs<DefinedOrUnknownSVal>();
Gabor Horvath28690922015-08-26 23:17:43 +0000953 const MemRegion *Region = getTrackRegion(*RegionSVal);
954 if (!Region)
955 return;
956
957 // When 0 is converted to nonnull mark it as contradicted.
958 if (DestNullability == Nullability::Nonnull) {
959 NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
960 if (Nullness == NullConstraint::IsNull) {
961 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
962 C.addTransition(State);
963 return;
964 }
965 }
966
967 const NullabilityState *TrackedNullability =
968 State->get<NullabilityMap>(Region);
969
970 if (!TrackedNullability) {
971 if (DestNullability != Nullability::Nullable)
972 return;
973 State = State->set<NullabilityMap>(Region,
974 NullabilityState(DestNullability, CE));
975 C.addTransition(State);
976 return;
977 }
978
979 if (TrackedNullability->getValue() != DestNullability &&
980 TrackedNullability->getValue() != Nullability::Contradicted) {
981 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
982 C.addTransition(State);
983 }
984}
985
Devin Coughlinc1986632015-11-24 19:15:11 +0000986/// For a given statement performing a bind, attempt to syntactically
987/// match the expression resulting in the bound value.
988static const Expr * matchValueExprForBind(const Stmt *S) {
989 // For `x = e` the value expression is the right-hand side.
990 if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
991 if (BinOp->getOpcode() == BO_Assign)
992 return BinOp->getRHS();
993 }
994
995 // For `int x = e` the value expression is the initializer.
996 if (auto *DS = dyn_cast<DeclStmt>(S)) {
997 if (DS->isSingleDecl()) {
998 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
999 if (!VD)
1000 return nullptr;
1001
1002 if (const Expr *Init = VD->getInit())
1003 return Init;
1004 }
1005 }
1006
1007 return nullptr;
1008}
1009
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +00001010/// Returns true if \param S is a DeclStmt for a local variable that
1011/// ObjC automated reference counting initialized with zero.
1012static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
1013 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
1014 // prevents false positives when a _Nonnull local variable cannot be
1015 // initialized with an initialization expression:
1016 // NSString * _Nonnull s; // no-warning
1017 // @autoreleasepool {
1018 // s = ...
1019 // }
1020 //
1021 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
1022 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
1023 // the zero-initialized definition will unexpectedly yield nil.
1024
1025 // Locals are only zero-initialized when automated reference counting
1026 // is turned on.
1027 if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
1028 return false;
1029
1030 auto *DS = dyn_cast<DeclStmt>(S);
1031 if (!DS || !DS->isSingleDecl())
1032 return false;
1033
1034 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
1035 if (!VD)
1036 return false;
1037
1038 // Sema only zero-initializes locals with ObjCLifetimes.
1039 if(!VD->getType().getQualifiers().hasObjCLifetime())
1040 return false;
1041
1042 const Expr *Init = VD->getInit();
1043 assert(Init && "ObjC local under ARC without initializer");
1044
1045 // Return false if the local is explicitly initialized (e.g., with '= nil').
1046 if (!isa<ImplicitValueInitExpr>(Init))
1047 return false;
1048
1049 return true;
1050}
1051
Gabor Horvath28690922015-08-26 23:17:43 +00001052/// Propagate the nullability information through binds and warn when nullable
1053/// pointer or null symbol is assigned to a pointer with a nonnull type.
1054void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
1055 CheckerContext &C) const {
1056 const TypedValueRegion *TVR =
1057 dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
1058 if (!TVR)
1059 return;
1060
1061 QualType LocType = TVR->getValueType();
1062 if (!LocType->isAnyPointerType())
1063 return;
1064
Gabor Horvathb47128a2015-09-03 23:16:21 +00001065 ProgramStateRef State = C.getState();
Devin Coughlin77942db2016-03-28 20:30:25 +00001066 if (State->get<InvariantViolated>())
Gabor Horvathb47128a2015-09-03 23:16:21 +00001067 return;
1068
Gabor Horvath28690922015-08-26 23:17:43 +00001069 auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1070 if (!ValDefOrUnknown)
1071 return;
1072
Gabor Horvath28690922015-08-26 23:17:43 +00001073 NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1074
1075 Nullability ValNullability = Nullability::Unspecified;
1076 if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1077 ValNullability = getNullabilityAnnotation(Sym->getType());
1078
1079 Nullability LocNullability = getNullabilityAnnotation(LocType);
Devin Coughlin4ac12422016-04-13 17:59:24 +00001080
1081 // If the type of the RHS expression is nonnull, don't warn. This
1082 // enables explicit suppression with a cast to nonnull.
1083 Nullability ValueExprTypeLevelNullability = Nullability::Unspecified;
1084 const Expr *ValueExpr = matchValueExprForBind(S);
1085 if (ValueExpr) {
1086 ValueExprTypeLevelNullability =
1087 getNullabilityAnnotation(lookThroughImplicitCasts(ValueExpr)->getType());
1088 }
1089
1090 bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
1091 RhsNullness == NullConstraint::IsNull);
Gabor Horvath28690922015-08-26 23:17:43 +00001092 if (Filter.CheckNullPassedToNonnull &&
Devin Coughlin4ac12422016-04-13 17:59:24 +00001093 NullAssignedToNonNull &&
Gabor Horvath28690922015-08-26 23:17:43 +00001094 ValNullability != Nullability::Nonnull &&
Devin Coughlin4ac12422016-04-13 17:59:24 +00001095 ValueExprTypeLevelNullability != Nullability::Nonnull &&
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +00001096 !isARCNilInitializedLocal(C, S)) {
Gabor Horvath28690922015-08-26 23:17:43 +00001097 static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
Devin Coughline39bd402015-09-16 22:03:05 +00001098 ExplodedNode *N = C.generateErrorNode(State, &Tag);
1099 if (!N)
1100 return;
Devin Coughlinc1986632015-11-24 19:15:11 +00001101
Devin Coughlin4ac12422016-04-13 17:59:24 +00001102
1103 const Stmt *ValueStmt = S;
1104 if (ValueExpr)
1105 ValueStmt = ValueExpr;
Devin Coughlinc1986632015-11-24 19:15:11 +00001106
Anna Zaks6d4e76b2016-12-15 22:55:15 +00001107 SmallString<256> SBuf;
1108 llvm::raw_svector_ostream OS(SBuf);
1109 OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
1110 OS << " assigned to a pointer which is expected to have non-null value";
1111 reportBugIfInvariantHolds(OS.str(),
Devin Coughlin77942db2016-03-28 20:30:25 +00001112 ErrorKind::NilAssignedToNonnull, N, nullptr, C,
Devin Coughlin4ac12422016-04-13 17:59:24 +00001113 ValueStmt);
Gabor Horvath28690922015-08-26 23:17:43 +00001114 return;
1115 }
Devin Coughlin4ac12422016-04-13 17:59:24 +00001116
1117 // If null was returned from a non-null function, mark the nullability
1118 // invariant as violated even if the diagnostic was suppressed.
1119 if (NullAssignedToNonNull) {
1120 State = State->set<InvariantViolated>(true);
1121 C.addTransition(State);
1122 return;
1123 }
1124
Gabor Horvath28690922015-08-26 23:17:43 +00001125 // Intentionally missing case: '0' is bound to a reference. It is handled by
1126 // the DereferenceChecker.
1127
1128 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1129 if (!ValueRegion)
1130 return;
1131
1132 const NullabilityState *TrackedNullability =
1133 State->get<NullabilityMap>(ValueRegion);
1134
1135 if (TrackedNullability) {
1136 if (RhsNullness == NullConstraint::IsNotNull ||
1137 TrackedNullability->getValue() != Nullability::Nullable)
1138 return;
1139 if (Filter.CheckNullablePassedToNonnull &&
1140 LocNullability == Nullability::Nonnull) {
1141 static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1142 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
Devin Coughlin77942db2016-03-28 20:30:25 +00001143 reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
1144 "which is expected to have non-null value",
1145 ErrorKind::NullableAssignedToNonnull, N,
1146 ValueRegion, C);
Gabor Horvath28690922015-08-26 23:17:43 +00001147 }
1148 return;
1149 }
1150
1151 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1152
1153 if (ValNullability == Nullability::Nullable) {
1154 // Trust the static information of the value more than the static
1155 // information on the location.
1156 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1157 State = State->set<NullabilityMap>(
1158 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1159 C.addTransition(State);
1160 return;
1161 }
1162
1163 if (LocNullability == Nullability::Nullable) {
1164 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1165 State = State->set<NullabilityMap>(
1166 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1167 C.addTransition(State);
1168 }
1169}
1170
1171void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1172 const char *NL, const char *Sep) const {
1173
1174 NullabilityMapTy B = State->get<NullabilityMap>();
1175
1176 if (B.isEmpty())
1177 return;
1178
1179 Out << Sep << NL;
1180
1181 for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1182 Out << I->first << " : ";
1183 I->second.print(Out);
1184 Out << NL;
1185 }
1186}
1187
Gabor Horvath29307352015-09-14 18:31:34 +00001188#define REGISTER_CHECKER(name, trackingRequired) \
Gabor Horvath28690922015-08-26 23:17:43 +00001189 void ento::register##name##Checker(CheckerManager &mgr) { \
1190 NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>(); \
1191 checker->Filter.Check##name = true; \
1192 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
Gabor Horvath29307352015-09-14 18:31:34 +00001193 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
Devin Coughlina1d9d752016-03-05 01:32:43 +00001194 checker->NoDiagnoseCallsToSystemHeaders = \
1195 checker->NoDiagnoseCallsToSystemHeaders || \
1196 mgr.getAnalyzerOptions().getBooleanOption( \
1197 "NoDiagnoseCallsToSystemHeaders", false, checker, true); \
Gabor Horvath28690922015-08-26 23:17:43 +00001198 }
1199
Gabor Horvath29307352015-09-14 18:31:34 +00001200// The checks are likely to be turned on by default and it is possible to do
1201// them without tracking any nullability related information. As an optimization
1202// no nullability information will be tracked when only these two checks are
1203// enables.
1204REGISTER_CHECKER(NullPassedToNonnull, false)
1205REGISTER_CHECKER(NullReturnedFromNonnull, false)
1206
1207REGISTER_CHECKER(NullableDereferenced, true)
1208REGISTER_CHECKER(NullablePassedToNonnull, true)
1209REGISTER_CHECKER(NullableReturnedFromNonnull, true)