blob: e096e2047f5ebae2b5be5d3a44a863bdbb06ad0a [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"
33#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
35
Anna Zaksad9e7ea2016-01-29 18:43:15 +000036#include "llvm/ADT/StringExtras.h"
37#include "llvm/Support/Path.h"
38
Gabor Horvath28690922015-08-26 23:17:43 +000039using namespace clang;
40using namespace ento;
41
42namespace {
43// Do not reorder! The getMostNullable method relies on the order.
44// Optimization: Most pointers expected to be unspecified. When a symbol has an
45// unspecified or nonnull type non of the rules would indicate any problem for
46// that symbol. For this reason only nullable and contradicted nullability are
47// stored for a symbol. When a symbol is already contradicted, it can not be
48// casted back to nullable.
49enum class Nullability : char {
50 Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
51 // not report any nullability related issue for this symbol.
52 // This nullability is propagated agressively to avoid false
53 // positive results. See the comment on getMostNullable method.
54 Nullable,
55 Unspecified,
56 Nonnull
57};
58
59/// Returns the most nullable nullability. This is used for message expressions
60/// like [reciever method], where the nullability of this expression is either
61/// the nullability of the receiver or the nullability of the return type of the
62/// method, depending on which is more nullable. Contradicted is considered to
63/// be the most nullable, to avoid false positive results.
Gabor Horvath3943adb2015-09-11 16:29:05 +000064Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
Gabor Horvath28690922015-08-26 23:17:43 +000065 return static_cast<Nullability>(
66 std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
67}
68
Gabor Horvath3943adb2015-09-11 16:29:05 +000069const char *getNullabilityString(Nullability Nullab) {
Gabor Horvath28690922015-08-26 23:17:43 +000070 switch (Nullab) {
71 case Nullability::Contradicted:
72 return "contradicted";
73 case Nullability::Nullable:
74 return "nullable";
75 case Nullability::Unspecified:
76 return "unspecified";
77 case Nullability::Nonnull:
78 return "nonnull";
79 }
Gabor Horvath3943adb2015-09-11 16:29:05 +000080 llvm_unreachable("Unexpected enumeration.");
Gabor Horvath28690922015-08-26 23:17:43 +000081 return "";
82}
83
84// These enums are used as an index to ErrorMessages array.
85enum class ErrorKind : int {
86 NilAssignedToNonnull,
87 NilPassedToNonnull,
88 NilReturnedToNonnull,
89 NullableAssignedToNonnull,
90 NullableReturnedToNonnull,
91 NullableDereferenced,
92 NullablePassedToNonnull
93};
94
Gabor Horvath28690922015-08-26 23:17:43 +000095class NullabilityChecker
96 : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
97 check::PostCall, check::PostStmt<ExplicitCastExpr>,
98 check::PostObjCMessage, check::DeadSymbols,
99 check::Event<ImplicitNullDerefEvent>> {
100 mutable std::unique_ptr<BugType> BT;
101
102public:
103 void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
104 void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
105 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
106 void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
107 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
108 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
109 void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
110 void checkEvent(ImplicitNullDerefEvent Event) const;
111
112 void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
113 const char *Sep) const override;
114
115 struct NullabilityChecksFilter {
116 DefaultBool CheckNullPassedToNonnull;
117 DefaultBool CheckNullReturnedFromNonnull;
118 DefaultBool CheckNullableDereferenced;
119 DefaultBool CheckNullablePassedToNonnull;
120 DefaultBool CheckNullableReturnedFromNonnull;
121
122 CheckName CheckNameNullPassedToNonnull;
123 CheckName CheckNameNullReturnedFromNonnull;
124 CheckName CheckNameNullableDereferenced;
125 CheckName CheckNameNullablePassedToNonnull;
126 CheckName CheckNameNullableReturnedFromNonnull;
127 };
128
129 NullabilityChecksFilter Filter;
Gabor Horvath29307352015-09-14 18:31:34 +0000130 // When set to false no nullability information will be tracked in
131 // NullabilityMap. It is possible to catch errors like passing a null pointer
132 // to a callee that expects nonnull argument without the information that is
133 // stroed in the NullabilityMap. This is an optimization.
134 DefaultBool NeedTracking;
Gabor Horvath28690922015-08-26 23:17:43 +0000135
136private:
137 class NullabilityBugVisitor
138 : public BugReporterVisitorImpl<NullabilityBugVisitor> {
139 public:
140 NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
141
142 void Profile(llvm::FoldingSetNodeID &ID) const override {
143 static int X = 0;
144 ID.AddPointer(&X);
145 ID.AddPointer(Region);
146 }
147
148 PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
149 const ExplodedNode *PrevN,
150 BugReporterContext &BRC,
151 BugReport &BR) override;
152
153 private:
154 // The tracked region.
155 const MemRegion *Region;
156 };
157
Gabor Horvathb47128a2015-09-03 23:16:21 +0000158 /// When any of the nonnull arguments of the analyzed function is null, do not
159 /// report anything and turn off the check.
160 ///
161 /// When \p SuppressPath is set to true, no more bugs will be reported on this
162 /// path by this checker.
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000163 void reportBugIfPreconditionHolds(StringRef Msg, ErrorKind Error,
164 ExplodedNode *N, const MemRegion *Region,
165 CheckerContext &C,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000166 const Stmt *ValueExpr = nullptr,
167 bool SuppressPath = false) const;
168
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000169 void reportBug(StringRef Msg, ErrorKind Error, ExplodedNode *N,
170 const MemRegion *Region, BugReporter &BR,
171 const Stmt *ValueExpr = nullptr) const {
Gabor Horvath28690922015-08-26 23:17:43 +0000172 if (!BT)
173 BT.reset(new BugType(this, "Nullability", "Memory error"));
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000174
175 auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
Gabor Horvath28690922015-08-26 23:17:43 +0000176 if (Region) {
177 R->markInteresting(Region);
178 R->addVisitor(llvm::make_unique<NullabilityBugVisitor>(Region));
179 }
180 if (ValueExpr) {
181 R->addRange(ValueExpr->getSourceRange());
182 if (Error == ErrorKind::NilAssignedToNonnull ||
183 Error == ErrorKind::NilPassedToNonnull ||
184 Error == ErrorKind::NilReturnedToNonnull)
185 bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
186 }
187 BR.emitReport(std::move(R));
188 }
Gabor Horvath29307352015-09-14 18:31:34 +0000189
190 /// If an SVal wraps a region that should be tracked, it will return a pointer
191 /// to the wrapped region. Otherwise it will return a nullptr.
192 const SymbolicRegion *getTrackRegion(SVal Val,
193 bool CheckSuperRegion = false) const;
Gabor Horvath28690922015-08-26 23:17:43 +0000194};
195
196class NullabilityState {
197public:
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
214private:
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
223bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
224 return Lhs.getValue() == Rhs.getValue() &&
225 Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
226}
227
228} // end anonymous namespace
229
230REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
231 NullabilityState)
232
Gabor Horvathb47128a2015-09-03 23:16:21 +0000233// 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.
238REGISTER_TRAIT_WITH_PROGRAMSTATE(PreconditionViolated, bool)
239
Gabor Horvath28690922015-08-26 23:17:43 +0000240enum class NullConstraint { IsNull, IsNotNull, Unknown };
241
242static 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
Gabor Horvath29307352015-09-14 18:31:34 +0000252const SymbolicRegion *
253NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
254 if (!NeedTracking)
255 return nullptr;
256
Gabor Horvath28690922015-08-26 23:17:43 +0000257 auto RegionSVal = Val.getAs<loc::MemRegionVal>();
258 if (!RegionSVal)
259 return nullptr;
260
261 const MemRegion *Region = RegionSVal->getRegion();
262
263 if (CheckSuperRegion) {
264 if (auto FieldReg = Region->getAs<FieldRegion>())
265 return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
Gabor Horvath3943adb2015-09-11 16:29:05 +0000266 if (auto ElementReg = Region->getAs<ElementRegion>())
Gabor Horvath28690922015-08-26 23:17:43 +0000267 return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
268 }
269
270 return dyn_cast<SymbolicRegion>(Region);
271}
272
273PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
274 const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
275 BugReport &BR) {
Gabor Horvath3943adb2015-09-11 16:29:05 +0000276 ProgramStateRef State = N->getState();
277 ProgramStateRef StatePrev = PrevN->getState();
Gabor Horvath28690922015-08-26 23:17:43 +0000278
Gabor Horvath3943adb2015-09-11 16:29:05 +0000279 const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
Gabor Horvath28690922015-08-26 23:17:43 +0000280 const NullabilityState *TrackedNullabPrev =
Gabor Horvath3943adb2015-09-11 16:29:05 +0000281 StatePrev->get<NullabilityMap>(Region);
Gabor Horvath28690922015-08-26 23:17:43 +0000282 if (!TrackedNullab)
283 return nullptr;
284
285 if (TrackedNullabPrev &&
286 TrackedNullabPrev->getValue() == TrackedNullab->getValue())
287 return nullptr;
288
289 // Retrieve the associated statement.
290 const Stmt *S = TrackedNullab->getNullabilitySource();
291 if (!S) {
292 ProgramPoint ProgLoc = N->getLocation();
293 if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
294 S = SP->getStmt();
295 }
296 }
297
298 if (!S)
299 return nullptr;
300
301 std::string InfoText =
302 (llvm::Twine("Nullability '") +
303 getNullabilityString(TrackedNullab->getValue()) + "' is infered")
304 .str();
305
306 // Generate the extra diagnostic.
307 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
308 N->getLocationContext());
309 return new PathDiagnosticEventPiece(Pos, InfoText, true, nullptr);
310}
311
312static Nullability getNullabilityAnnotation(QualType Type) {
313 const auto *AttrType = Type->getAs<AttributedType>();
314 if (!AttrType)
315 return Nullability::Unspecified;
316 if (AttrType->getAttrKind() == AttributedType::attr_nullable)
317 return Nullability::Nullable;
318 else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
319 return Nullability::Nonnull;
320 return Nullability::Unspecified;
321}
322
Gabor Horvathb47128a2015-09-03 23:16:21 +0000323template <typename ParamVarDeclRange>
324static bool
325checkParamsForPreconditionViolation(const ParamVarDeclRange &Params,
326 ProgramStateRef State,
327 const LocationContext *LocCtxt) {
328 for (const auto *ParamDecl : Params) {
329 if (ParamDecl->isParameterPack())
330 break;
331
332 if (getNullabilityAnnotation(ParamDecl->getType()) != Nullability::Nonnull)
333 continue;
334
335 auto RegVal = State->getLValue(ParamDecl, LocCtxt)
336 .template getAs<loc::MemRegionVal>();
337 if (!RegVal)
338 continue;
339
340 auto ParamValue = State->getSVal(RegVal->getRegion())
341 .template getAs<DefinedOrUnknownSVal>();
342 if (!ParamValue)
343 continue;
344
345 if (getNullConstraint(*ParamValue, State) == NullConstraint::IsNull) {
346 return true;
347 }
348 }
349 return false;
350}
351
352static bool checkPreconditionViolation(ProgramStateRef State, ExplodedNode *N,
353 CheckerContext &C) {
354 if (State->get<PreconditionViolated>())
355 return true;
356
357 const LocationContext *LocCtxt = C.getLocationContext();
358 const Decl *D = LocCtxt->getDecl();
359 if (!D)
360 return false;
361
Devin Coughlin851da712016-01-15 21:35:40 +0000362 ArrayRef<ParmVarDecl*> Params;
363 if (const auto *BD = dyn_cast<BlockDecl>(D))
364 Params = BD->parameters();
365 else if (const auto *FD = dyn_cast<FunctionDecl>(D))
366 Params = FD->parameters();
367 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
368 Params = MD->parameters();
369 else
Gabor Horvathb47128a2015-09-03 23:16:21 +0000370 return false;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000371
Devin Coughlin851da712016-01-15 21:35:40 +0000372 if (checkParamsForPreconditionViolation(Params, State, LocCtxt)) {
373 if (!N->isSink())
374 C.addTransition(State->set<PreconditionViolated>(true), N);
375 return true;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000376 }
377 return false;
378}
379
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000380void NullabilityChecker::reportBugIfPreconditionHolds(StringRef Msg,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000381 ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
382 CheckerContext &C, const Stmt *ValueExpr, bool SuppressPath) const {
383 ProgramStateRef OriginalState = N->getState();
384
385 if (checkPreconditionViolation(OriginalState, N, C))
386 return;
387 if (SuppressPath) {
388 OriginalState = OriginalState->set<PreconditionViolated>(true);
389 N = C.addTransition(OriginalState, N);
390 }
391
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000392 reportBug(Msg, Error, N, Region, C.getBugReporter(), ValueExpr);
Gabor Horvathb47128a2015-09-03 23:16:21 +0000393}
394
Gabor Horvath28690922015-08-26 23:17:43 +0000395/// Cleaning up the program state.
396void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
397 CheckerContext &C) const {
Gabor Horvathbe87d5b2015-09-14 20:31:46 +0000398 if (!SR.hasDeadSymbols())
399 return;
400
Gabor Horvath28690922015-08-26 23:17:43 +0000401 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) {
Gabor Horvathbe87d5b2015-09-14 20:31:46 +0000406 const auto *Region = I->first->getAs<SymbolicRegion>();
407 assert(Region && "Non-symbolic region is tracked.");
408 if (SR.isDead(Region->getSymbol())) {
Gabor Horvath28690922015-08-26 23:17:43 +0000409 State = State->remove<NullabilityMap>(I->first);
410 }
411 }
Gabor Horvathb47128a2015-09-03 23:16:21 +0000412 // When one of the nonnull arguments are constrained to be null, nullability
413 // preconditions are violated. It is not enough to check this only when we
414 // actually report an error, because at that time interesting symbols might be
415 // reaped.
416 if (checkPreconditionViolation(State, C.getPredecessor(), C))
417 return;
418 C.addTransition(State);
Gabor Horvath28690922015-08-26 23:17:43 +0000419}
420
421/// This callback triggers when a pointer is dereferenced and the analyzer does
422/// not know anything about the value of that pointer. When that pointer is
423/// nullable, this code emits a warning.
424void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000425 if (Event.SinkNode->getState()->get<PreconditionViolated>())
426 return;
427
Gabor Horvath28690922015-08-26 23:17:43 +0000428 const MemRegion *Region =
429 getTrackRegion(Event.Location, /*CheckSuperregion=*/true);
430 if (!Region)
431 return;
432
433 ProgramStateRef State = Event.SinkNode->getState();
434 const NullabilityState *TrackedNullability =
435 State->get<NullabilityMap>(Region);
436
437 if (!TrackedNullability)
438 return;
439
440 if (Filter.CheckNullableDereferenced &&
441 TrackedNullability->getValue() == Nullability::Nullable) {
442 BugReporter &BR = *Event.BR;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000443 // Do not suppress errors on defensive code paths, because dereferencing
444 // a nullable pointer is always an error.
Gabor Horvath8d3ad6b2015-08-27 18:49:07 +0000445 if (Event.IsDirectDereference)
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000446 reportBug("Nullable pointer is dereferenced",
447 ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
448 else {
449 reportBug("Nullable pointer is passed to a callee that requires a "
450 "non-null", ErrorKind::NullablePassedToNonnull,
451 Event.SinkNode, Region, BR);
452 }
Gabor Horvath28690922015-08-26 23:17:43 +0000453 }
454}
455
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000456/// Find the outermost subexpression of E that is not an implicit cast.
457/// This looks through the implicit casts to _Nonnull that ARC adds to
458/// return expressions of ObjC types when the return type of the function or
459/// method is non-null but the express is not.
460static const Expr *lookThroughImplicitCasts(const Expr *E) {
461 assert(E);
462
463 while (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
464 E = ICE->getSubExpr();
465 }
466
467 return E;
468}
469
Gabor Horvath28690922015-08-26 23:17:43 +0000470/// This method check when nullable pointer or null value is returned from a
471/// function that has nonnull return type.
472///
473/// TODO: when nullability preconditons are violated, it is ok to violate the
474/// nullability postconditons (i.e.: when one of the nonnull parameters are null
475/// this check should not report any nullability related issue).
476void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
477 CheckerContext &C) const {
478 auto RetExpr = S->getRetValue();
479 if (!RetExpr)
480 return;
481
482 if (!RetExpr->getType()->isAnyPointerType())
483 return;
484
485 ProgramStateRef State = C.getState();
Gabor Horvathb47128a2015-09-03 23:16:21 +0000486 if (State->get<PreconditionViolated>())
487 return;
488
Gabor Horvath28690922015-08-26 23:17:43 +0000489 auto RetSVal =
490 State->getSVal(S, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
491 if (!RetSVal)
492 return;
493
Devin Coughlinde217672016-01-28 22:23:34 +0000494 bool InSuppressedMethodFamily = false;
Devin Coughlin4a330202016-01-22 01:01:11 +0000495
Devin Coughlin851da712016-01-15 21:35:40 +0000496 QualType RequiredRetType;
Gabor Horvath28690922015-08-26 23:17:43 +0000497 AnalysisDeclContext *DeclCtxt =
498 C.getLocationContext()->getAnalysisDeclContext();
Devin Coughlin851da712016-01-15 21:35:40 +0000499 const Decl *D = DeclCtxt->getDecl();
Devin Coughlin4a330202016-01-22 01:01:11 +0000500 if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
Devin Coughlinde217672016-01-28 22:23:34 +0000501 // HACK: This is a big hammer to avoid warning when there are defensive
502 // nil checks in -init and -copy methods. We should add more sophisticated
503 // logic here to suppress on common defensive idioms but still
504 // warn when there is a likely problem.
505 ObjCMethodFamily Family = MD->getMethodFamily();
506 if (OMF_init == Family || OMF_copy == Family || OMF_mutableCopy == Family)
507 InSuppressedMethodFamily = true;
508
Devin Coughlin851da712016-01-15 21:35:40 +0000509 RequiredRetType = MD->getReturnType();
Devin Coughlin4a330202016-01-22 01:01:11 +0000510 } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
Devin Coughlin851da712016-01-15 21:35:40 +0000511 RequiredRetType = FD->getReturnType();
Devin Coughlin4a330202016-01-22 01:01:11 +0000512 } else {
Gabor Horvath28690922015-08-26 23:17:43 +0000513 return;
Devin Coughlin4a330202016-01-22 01:01:11 +0000514 }
Gabor Horvath28690922015-08-26 23:17:43 +0000515
516 NullConstraint Nullness = getNullConstraint(*RetSVal, State);
517
Devin Coughlin851da712016-01-15 21:35:40 +0000518 Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
Gabor Horvath28690922015-08-26 23:17:43 +0000519
Devin Coughlin755baa42015-12-29 17:40:49 +0000520 // If the returned value is null but the type of the expression
521 // generating it is nonnull then we will suppress the diagnostic.
522 // This enables explicit suppression when returning a nil literal in a
523 // function with a _Nonnull return type:
524 // return (NSString * _Nonnull)0;
525 Nullability RetExprTypeLevelNullability =
Devin Coughlin5a3843e2016-01-18 18:53:33 +0000526 getNullabilityAnnotation(lookThroughImplicitCasts(RetExpr)->getType());
Devin Coughlin755baa42015-12-29 17:40:49 +0000527
Gabor Horvath28690922015-08-26 23:17:43 +0000528 if (Filter.CheckNullReturnedFromNonnull &&
529 Nullness == NullConstraint::IsNull &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000530 RetExprTypeLevelNullability != Nullability::Nonnull &&
Devin Coughlin4a330202016-01-22 01:01:11 +0000531 RequiredNullability == Nullability::Nonnull &&
Devin Coughlinde217672016-01-28 22:23:34 +0000532 !InSuppressedMethodFamily) {
Gabor Horvath28690922015-08-26 23:17:43 +0000533 static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
Devin Coughline39bd402015-09-16 22:03:05 +0000534 ExplodedNode *N = C.generateErrorNode(State, &Tag);
535 if (!N)
536 return;
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000537
538 SmallString<256> SBuf;
539 llvm::raw_svector_ostream OS(SBuf);
540 OS << "Null is returned from a " << C.getDeclDescription(D) <<
541 " that is expected to return a non-null value";
542
543 reportBugIfPreconditionHolds(OS.str(),
544 ErrorKind::NilReturnedToNonnull, N, nullptr, C,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000545 RetExpr);
Gabor Horvath28690922015-08-26 23:17:43 +0000546 return;
547 }
548
549 const MemRegion *Region = getTrackRegion(*RetSVal);
550 if (!Region)
551 return;
552
553 const NullabilityState *TrackedNullability =
554 State->get<NullabilityMap>(Region);
555 if (TrackedNullability) {
556 Nullability TrackedNullabValue = TrackedNullability->getValue();
557 if (Filter.CheckNullableReturnedFromNonnull &&
558 Nullness != NullConstraint::IsNotNull &&
559 TrackedNullabValue == Nullability::Nullable &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000560 RequiredNullability == Nullability::Nonnull) {
Gabor Horvath28690922015-08-26 23:17:43 +0000561 static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
562 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000563
564 SmallString<256> SBuf;
565 llvm::raw_svector_ostream OS(SBuf);
566 OS << "Nullable pointer is returned from a " << C.getDeclDescription(D) <<
567 " that is expected to return a non-null value";
568
569 reportBugIfPreconditionHolds(OS.str(),
570 ErrorKind::NullableReturnedToNonnull, N,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000571 Region, C);
Gabor Horvath28690922015-08-26 23:17:43 +0000572 }
573 return;
574 }
Devin Coughlin755baa42015-12-29 17:40:49 +0000575 if (RequiredNullability == Nullability::Nullable) {
Gabor Horvath28690922015-08-26 23:17:43 +0000576 State = State->set<NullabilityMap>(Region,
Devin Coughlin755baa42015-12-29 17:40:49 +0000577 NullabilityState(RequiredNullability,
578 S));
Gabor Horvath28690922015-08-26 23:17:43 +0000579 C.addTransition(State);
580 }
581}
582
583/// This callback warns when a nullable pointer or a null value is passed to a
584/// function that expects its argument to be nonnull.
585void NullabilityChecker::checkPreCall(const CallEvent &Call,
586 CheckerContext &C) const {
587 if (!Call.getDecl())
588 return;
589
590 ProgramStateRef State = C.getState();
Gabor Horvathb47128a2015-09-03 23:16:21 +0000591 if (State->get<PreconditionViolated>())
592 return;
593
Gabor Horvath28690922015-08-26 23:17:43 +0000594 ProgramStateRef OrigState = State;
595
596 unsigned Idx = 0;
597 for (const ParmVarDecl *Param : Call.parameters()) {
598 if (Param->isParameterPack())
599 break;
600
601 const Expr *ArgExpr = nullptr;
602 if (Idx < Call.getNumArgs())
603 ArgExpr = Call.getArgExpr(Idx);
604 auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
605 if (!ArgSVal)
606 continue;
607
608 if (!Param->getType()->isAnyPointerType() &&
609 !Param->getType()->isReferenceType())
610 continue;
611
612 NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
613
Devin Coughlin755baa42015-12-29 17:40:49 +0000614 Nullability RequiredNullability =
615 getNullabilityAnnotation(Param->getType());
616 Nullability ArgExprTypeLevelNullability =
Gabor Horvath28690922015-08-26 23:17:43 +0000617 getNullabilityAnnotation(ArgExpr->getType());
618
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000619 unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
620
Gabor Horvath28690922015-08-26 23:17:43 +0000621 if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000622 ArgExprTypeLevelNullability != Nullability::Nonnull &&
623 RequiredNullability == Nullability::Nonnull) {
Devin Coughline39bd402015-09-16 22:03:05 +0000624 ExplodedNode *N = C.generateErrorNode(State);
625 if (!N)
626 return;
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000627 SmallString<256> SBuf;
628 llvm::raw_svector_ostream OS(SBuf);
629 OS << "Null passed to a callee that requires a non-null " << ParamIdx
630 << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
631 reportBugIfPreconditionHolds(OS.str(), ErrorKind::NilPassedToNonnull, N,
632 nullptr, C,
633 ArgExpr, /*SuppressPath=*/false);
Gabor Horvath28690922015-08-26 23:17:43 +0000634 return;
635 }
636
637 const MemRegion *Region = getTrackRegion(*ArgSVal);
638 if (!Region)
639 continue;
640
641 const NullabilityState *TrackedNullability =
642 State->get<NullabilityMap>(Region);
643
644 if (TrackedNullability) {
645 if (Nullness == NullConstraint::IsNotNull ||
646 TrackedNullability->getValue() != Nullability::Nullable)
647 continue;
648
649 if (Filter.CheckNullablePassedToNonnull &&
Devin Coughlin755baa42015-12-29 17:40:49 +0000650 RequiredNullability == Nullability::Nonnull) {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000651 ExplodedNode *N = C.addTransition(State);
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000652 SmallString<256> SBuf;
653 llvm::raw_svector_ostream OS(SBuf);
654 OS << "Nullable pointer is passed to a callee that requires a non-null "
655 << ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
656 reportBugIfPreconditionHolds(OS.str(),
657 ErrorKind::NullablePassedToNonnull, N,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000658 Region, C, ArgExpr, /*SuppressPath=*/true);
Gabor Horvath28690922015-08-26 23:17:43 +0000659 return;
660 }
661 if (Filter.CheckNullableDereferenced &&
662 Param->getType()->isReferenceType()) {
Gabor Horvathb47128a2015-09-03 23:16:21 +0000663 ExplodedNode *N = C.addTransition(State);
Anna Zaksad9e7ea2016-01-29 18:43:15 +0000664 reportBugIfPreconditionHolds("Nullable pointer is dereferenced",
665 ErrorKind::NullableDereferenced, N, Region,
Gabor Horvathb47128a2015-09-03 23:16:21 +0000666 C, ArgExpr, /*SuppressPath=*/true);
Gabor Horvath28690922015-08-26 23:17:43 +0000667 return;
668 }
669 continue;
670 }
671 // No tracked nullability yet.
Devin Coughlin755baa42015-12-29 17:40:49 +0000672 if (ArgExprTypeLevelNullability != Nullability::Nullable)
Gabor Horvath28690922015-08-26 23:17:43 +0000673 continue;
674 State = State->set<NullabilityMap>(
Devin Coughlin755baa42015-12-29 17:40:49 +0000675 Region, NullabilityState(ArgExprTypeLevelNullability, ArgExpr));
Gabor Horvath28690922015-08-26 23:17:43 +0000676 }
677 if (State != OrigState)
678 C.addTransition(State);
679}
680
681/// Suppress the nullability warnings for some functions.
682void NullabilityChecker::checkPostCall(const CallEvent &Call,
683 CheckerContext &C) const {
684 auto Decl = Call.getDecl();
685 if (!Decl)
686 return;
687 // ObjC Messages handles in a different callback.
688 if (Call.getKind() == CE_ObjCMessage)
689 return;
690 const FunctionType *FuncType = Decl->getFunctionType();
691 if (!FuncType)
692 return;
693 QualType ReturnType = FuncType->getReturnType();
694 if (!ReturnType->isAnyPointerType())
695 return;
Gabor Horvathb47128a2015-09-03 23:16:21 +0000696 ProgramStateRef State = C.getState();
697 if (State->get<PreconditionViolated>())
698 return;
699
Gabor Horvath28690922015-08-26 23:17:43 +0000700 const MemRegion *Region = getTrackRegion(Call.getReturnValue());
701 if (!Region)
702 return;
Gabor Horvath28690922015-08-26 23:17:43 +0000703
704 // CG headers are misannotated. Do not warn for symbols that are the results
705 // of CG calls.
706 const SourceManager &SM = C.getSourceManager();
707 StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
708 if (llvm::sys::path::filename(FilePath).startswith("CG")) {
709 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
710 C.addTransition(State);
711 return;
712 }
713
714 const NullabilityState *TrackedNullability =
715 State->get<NullabilityMap>(Region);
716
717 if (!TrackedNullability &&
718 getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
719 State = State->set<NullabilityMap>(Region, Nullability::Nullable);
720 C.addTransition(State);
721 }
722}
723
724static Nullability getReceiverNullability(const ObjCMethodCall &M,
725 ProgramStateRef State) {
Gabor Horvath28690922015-08-26 23:17:43 +0000726 if (M.isReceiverSelfOrSuper()) {
727 // For super and super class receivers we assume that the receiver is
728 // nonnull.
Gabor Horvath3943adb2015-09-11 16:29:05 +0000729 return Nullability::Nonnull;
Gabor Horvath28690922015-08-26 23:17:43 +0000730 }
Gabor Horvath3943adb2015-09-11 16:29:05 +0000731 // Otherwise look up nullability in the state.
732 SVal Receiver = M.getReceiverSVal();
733 if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
734 // If the receiver is constrained to be nonnull, assume that it is nonnull
735 // regardless of its type.
736 NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
737 if (Nullness == NullConstraint::IsNotNull)
738 return Nullability::Nonnull;
739 }
740 auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
741 if (ValueRegionSVal) {
742 const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
743 assert(SelfRegion);
744
745 const NullabilityState *TrackedSelfNullability =
746 State->get<NullabilityMap>(SelfRegion);
747 if (TrackedSelfNullability)
748 return TrackedSelfNullability->getValue();
749 }
750 return Nullability::Unspecified;
Gabor Horvath28690922015-08-26 23:17:43 +0000751}
752
753/// Calculate the nullability of the result of a message expr based on the
754/// nullability of the receiver, the nullability of the return value, and the
755/// constraints.
756void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
757 CheckerContext &C) const {
758 auto Decl = M.getDecl();
759 if (!Decl)
760 return;
761 QualType RetType = Decl->getReturnType();
762 if (!RetType->isAnyPointerType())
763 return;
764
Gabor Horvathb47128a2015-09-03 23:16:21 +0000765 ProgramStateRef State = C.getState();
766 if (State->get<PreconditionViolated>())
767 return;
768
Gabor Horvath28690922015-08-26 23:17:43 +0000769 const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
770 if (!ReturnRegion)
771 return;
772
Gabor Horvath28690922015-08-26 23:17:43 +0000773 auto Interface = Decl->getClassInterface();
774 auto Name = Interface ? Interface->getName() : "";
775 // In order to reduce the noise in the diagnostics generated by this checker,
776 // some framework and programming style based heuristics are used. These
777 // heuristics are for Cocoa APIs which have NS prefix.
778 if (Name.startswith("NS")) {
779 // Developers rely on dynamic invariants such as an item should be available
780 // in a collection, or a collection is not empty often. Those invariants can
781 // not be inferred by any static analysis tool. To not to bother the users
782 // with too many false positives, every item retrieval function should be
783 // ignored for collections. The instance methods of dictionaries in Cocoa
784 // are either item retrieval related or not interesting nullability wise.
785 // Using this fact, to keep the code easier to read just ignore the return
786 // value of every instance method of dictionaries.
787 if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
788 State =
789 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
790 C.addTransition(State);
791 return;
792 }
793 // For similar reasons ignore some methods of Cocoa arrays.
794 StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
795 if (Name.find("Array") != StringRef::npos &&
796 (FirstSelectorSlot == "firstObject" ||
797 FirstSelectorSlot == "lastObject")) {
798 State =
799 State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
800 C.addTransition(State);
801 return;
802 }
803
804 // Encoding related methods of string should not fail when lossless
805 // encodings are used. Using lossless encodings is so frequent that ignoring
806 // this class of methods reduced the emitted diagnostics by about 30% on
807 // some projects (and all of that was false positives).
808 if (Name.find("String") != StringRef::npos) {
809 for (auto Param : M.parameters()) {
810 if (Param->getName() == "encoding") {
811 State = State->set<NullabilityMap>(ReturnRegion,
812 Nullability::Contradicted);
813 C.addTransition(State);
814 return;
815 }
816 }
817 }
818 }
819
820 const ObjCMessageExpr *Message = M.getOriginExpr();
821 Nullability SelfNullability = getReceiverNullability(M, State);
822
823 const NullabilityState *NullabilityOfReturn =
824 State->get<NullabilityMap>(ReturnRegion);
825
826 if (NullabilityOfReturn) {
827 // When we have a nullability tracked for the return value, the nullability
828 // of the expression will be the most nullable of the receiver and the
829 // return value.
830 Nullability RetValTracked = NullabilityOfReturn->getValue();
831 Nullability ComputedNullab =
832 getMostNullable(RetValTracked, SelfNullability);
833 if (ComputedNullab != RetValTracked &&
834 ComputedNullab != Nullability::Unspecified) {
835 const Stmt *NullabilitySource =
836 ComputedNullab == RetValTracked
837 ? NullabilityOfReturn->getNullabilitySource()
838 : Message->getInstanceReceiver();
839 State = State->set<NullabilityMap>(
840 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
841 C.addTransition(State);
842 }
843 return;
844 }
845
846 // No tracked information. Use static type information for return value.
847 Nullability RetNullability = getNullabilityAnnotation(RetType);
848
849 // Properties might be computed. For this reason the static analyzer creates a
850 // new symbol each time an unknown property is read. To avoid false pozitives
851 // do not treat unknown properties as nullable, even when they explicitly
852 // marked nullable.
853 if (M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined)
854 RetNullability = Nullability::Nonnull;
855
856 Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
857 if (ComputedNullab == Nullability::Nullable) {
858 const Stmt *NullabilitySource = ComputedNullab == RetNullability
859 ? Message
860 : Message->getInstanceReceiver();
861 State = State->set<NullabilityMap>(
862 ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
863 C.addTransition(State);
864 }
865}
866
867/// Explicit casts are trusted. If there is a disagreement in the nullability
868/// annotations in the destination and the source or '0' is casted to nonnull
869/// track the value as having contraditory nullability. This will allow users to
870/// suppress warnings.
871void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
872 CheckerContext &C) const {
873 QualType OriginType = CE->getSubExpr()->getType();
874 QualType DestType = CE->getType();
875 if (!OriginType->isAnyPointerType())
876 return;
877 if (!DestType->isAnyPointerType())
878 return;
879
Gabor Horvathb47128a2015-09-03 23:16:21 +0000880 ProgramStateRef State = C.getState();
881 if (State->get<PreconditionViolated>())
882 return;
883
Gabor Horvath28690922015-08-26 23:17:43 +0000884 Nullability DestNullability = getNullabilityAnnotation(DestType);
885
886 // No explicit nullability in the destination type, so this cast does not
887 // change the nullability.
888 if (DestNullability == Nullability::Unspecified)
889 return;
890
Gabor Horvath28690922015-08-26 23:17:43 +0000891 auto RegionSVal =
892 State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
893 const MemRegion *Region = getTrackRegion(*RegionSVal);
894 if (!Region)
895 return;
896
897 // When 0 is converted to nonnull mark it as contradicted.
898 if (DestNullability == Nullability::Nonnull) {
899 NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
900 if (Nullness == NullConstraint::IsNull) {
901 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
902 C.addTransition(State);
903 return;
904 }
905 }
906
907 const NullabilityState *TrackedNullability =
908 State->get<NullabilityMap>(Region);
909
910 if (!TrackedNullability) {
911 if (DestNullability != Nullability::Nullable)
912 return;
913 State = State->set<NullabilityMap>(Region,
914 NullabilityState(DestNullability, CE));
915 C.addTransition(State);
916 return;
917 }
918
919 if (TrackedNullability->getValue() != DestNullability &&
920 TrackedNullability->getValue() != Nullability::Contradicted) {
921 State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
922 C.addTransition(State);
923 }
924}
925
Devin Coughlinc1986632015-11-24 19:15:11 +0000926/// For a given statement performing a bind, attempt to syntactically
927/// match the expression resulting in the bound value.
928static const Expr * matchValueExprForBind(const Stmt *S) {
929 // For `x = e` the value expression is the right-hand side.
930 if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
931 if (BinOp->getOpcode() == BO_Assign)
932 return BinOp->getRHS();
933 }
934
935 // For `int x = e` the value expression is the initializer.
936 if (auto *DS = dyn_cast<DeclStmt>(S)) {
937 if (DS->isSingleDecl()) {
938 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
939 if (!VD)
940 return nullptr;
941
942 if (const Expr *Init = VD->getInit())
943 return Init;
944 }
945 }
946
947 return nullptr;
948}
949
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +0000950/// Returns true if \param S is a DeclStmt for a local variable that
951/// ObjC automated reference counting initialized with zero.
952static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
953 // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
954 // prevents false positives when a _Nonnull local variable cannot be
955 // initialized with an initialization expression:
956 // NSString * _Nonnull s; // no-warning
957 // @autoreleasepool {
958 // s = ...
959 // }
960 //
961 // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
962 // uninitialized in Sema's UninitializedValues analysis to warn when a use of
963 // the zero-initialized definition will unexpectedly yield nil.
964
965 // Locals are only zero-initialized when automated reference counting
966 // is turned on.
967 if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
968 return false;
969
970 auto *DS = dyn_cast<DeclStmt>(S);
971 if (!DS || !DS->isSingleDecl())
972 return false;
973
974 auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
975 if (!VD)
976 return false;
977
978 // Sema only zero-initializes locals with ObjCLifetimes.
979 if(!VD->getType().getQualifiers().hasObjCLifetime())
980 return false;
981
982 const Expr *Init = VD->getInit();
983 assert(Init && "ObjC local under ARC without initializer");
984
985 // Return false if the local is explicitly initialized (e.g., with '= nil').
986 if (!isa<ImplicitValueInitExpr>(Init))
987 return false;
988
989 return true;
990}
991
Gabor Horvath28690922015-08-26 23:17:43 +0000992/// Propagate the nullability information through binds and warn when nullable
993/// pointer or null symbol is assigned to a pointer with a nonnull type.
994void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
995 CheckerContext &C) const {
996 const TypedValueRegion *TVR =
997 dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
998 if (!TVR)
999 return;
1000
1001 QualType LocType = TVR->getValueType();
1002 if (!LocType->isAnyPointerType())
1003 return;
1004
Gabor Horvathb47128a2015-09-03 23:16:21 +00001005 ProgramStateRef State = C.getState();
1006 if (State->get<PreconditionViolated>())
1007 return;
1008
Gabor Horvath28690922015-08-26 23:17:43 +00001009 auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
1010 if (!ValDefOrUnknown)
1011 return;
1012
Gabor Horvath28690922015-08-26 23:17:43 +00001013 NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
1014
1015 Nullability ValNullability = Nullability::Unspecified;
1016 if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
1017 ValNullability = getNullabilityAnnotation(Sym->getType());
1018
1019 Nullability LocNullability = getNullabilityAnnotation(LocType);
1020 if (Filter.CheckNullPassedToNonnull &&
1021 RhsNullness == NullConstraint::IsNull &&
1022 ValNullability != Nullability::Nonnull &&
Devin Coughlin3ab8b2e72015-12-29 23:44:19 +00001023 LocNullability == Nullability::Nonnull &&
1024 !isARCNilInitializedLocal(C, S)) {
Gabor Horvath28690922015-08-26 23:17:43 +00001025 static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
Devin Coughline39bd402015-09-16 22:03:05 +00001026 ExplodedNode *N = C.generateErrorNode(State, &Tag);
1027 if (!N)
1028 return;
Devin Coughlinc1986632015-11-24 19:15:11 +00001029
1030 const Stmt *ValueExpr = matchValueExprForBind(S);
1031 if (!ValueExpr)
1032 ValueExpr = S;
1033
Anna Zaksad9e7ea2016-01-29 18:43:15 +00001034 reportBugIfPreconditionHolds("Null is assigned to a pointer which is "
1035 "expected to have non-null value",
1036 ErrorKind::NilAssignedToNonnull, N, nullptr, C,
Devin Coughlinc1986632015-11-24 19:15:11 +00001037 ValueExpr);
Gabor Horvath28690922015-08-26 23:17:43 +00001038 return;
1039 }
1040 // Intentionally missing case: '0' is bound to a reference. It is handled by
1041 // the DereferenceChecker.
1042
1043 const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
1044 if (!ValueRegion)
1045 return;
1046
1047 const NullabilityState *TrackedNullability =
1048 State->get<NullabilityMap>(ValueRegion);
1049
1050 if (TrackedNullability) {
1051 if (RhsNullness == NullConstraint::IsNotNull ||
1052 TrackedNullability->getValue() != Nullability::Nullable)
1053 return;
1054 if (Filter.CheckNullablePassedToNonnull &&
1055 LocNullability == Nullability::Nonnull) {
1056 static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
1057 ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
Anna Zaksad9e7ea2016-01-29 18:43:15 +00001058 reportBugIfPreconditionHolds("Nullable pointer is assigned to a pointer "
1059 "which is expected to have non-null value",
1060 ErrorKind::NullableAssignedToNonnull, N,
Gabor Horvathb47128a2015-09-03 23:16:21 +00001061 ValueRegion, C);
Gabor Horvath28690922015-08-26 23:17:43 +00001062 }
1063 return;
1064 }
1065
1066 const auto *BinOp = dyn_cast<BinaryOperator>(S);
1067
1068 if (ValNullability == Nullability::Nullable) {
1069 // Trust the static information of the value more than the static
1070 // information on the location.
1071 const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
1072 State = State->set<NullabilityMap>(
1073 ValueRegion, NullabilityState(ValNullability, NullabilitySource));
1074 C.addTransition(State);
1075 return;
1076 }
1077
1078 if (LocNullability == Nullability::Nullable) {
1079 const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
1080 State = State->set<NullabilityMap>(
1081 ValueRegion, NullabilityState(LocNullability, NullabilitySource));
1082 C.addTransition(State);
1083 }
1084}
1085
1086void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
1087 const char *NL, const char *Sep) const {
1088
1089 NullabilityMapTy B = State->get<NullabilityMap>();
1090
1091 if (B.isEmpty())
1092 return;
1093
1094 Out << Sep << NL;
1095
1096 for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
1097 Out << I->first << " : ";
1098 I->second.print(Out);
1099 Out << NL;
1100 }
1101}
1102
Gabor Horvath29307352015-09-14 18:31:34 +00001103#define REGISTER_CHECKER(name, trackingRequired) \
Gabor Horvath28690922015-08-26 23:17:43 +00001104 void ento::register##name##Checker(CheckerManager &mgr) { \
1105 NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>(); \
1106 checker->Filter.Check##name = true; \
1107 checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
Gabor Horvath29307352015-09-14 18:31:34 +00001108 checker->NeedTracking = checker->NeedTracking || trackingRequired; \
Gabor Horvath28690922015-08-26 23:17:43 +00001109 }
1110
Gabor Horvath29307352015-09-14 18:31:34 +00001111// The checks are likely to be turned on by default and it is possible to do
1112// them without tracking any nullability related information. As an optimization
1113// no nullability information will be tracked when only these two checks are
1114// enables.
1115REGISTER_CHECKER(NullPassedToNonnull, false)
1116REGISTER_CHECKER(NullReturnedFromNonnull, false)
1117
1118REGISTER_CHECKER(NullableDereferenced, true)
1119REGISTER_CHECKER(NullablePassedToNonnull, true)
1120REGISTER_CHECKER(NullableReturnedFromNonnull, true)