clang  7.0.0
TrustNonnullChecker.cpp
Go to the documentation of this file.
1 //== TrustNonnullChecker.cpp - Checker for trusting annotations -*- 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 adds an assumption that methods annotated with _Nonnull
11 // which come from system headers actually return a non-null pointer.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ClangSACheckers.h"
21 
22 using namespace clang;
23 using namespace ento;
24 
25 namespace {
26 
27 class TrustNonnullChecker : public Checker<check::PostCall> {
28 private:
29  /// \returns Whether we trust the result of the method call to be
30  /// a non-null pointer.
31  bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
32  QualType ExprRetType = Call.getResultType();
33  if (!ExprRetType->isAnyPointerType())
34  return false;
35 
37  return true;
38 
39  // The logic for ObjC instance method calls is more complicated,
40  // as the return value is nil when the receiver is nil.
41  if (!isa<ObjCMethodCall>(&Call))
42  return false;
43 
44  const auto *MCall = cast<ObjCMethodCall>(&Call);
45  const ObjCMethodDecl *MD = MCall->getDecl();
46 
47  // Distrust protocols.
48  if (isa<ObjCProtocolDecl>(MD->getDeclContext()))
49  return false;
50 
51  QualType DeclRetType = MD->getReturnType();
53  return false;
54 
55  // For class messages it is sufficient for the declaration to be
56  // annotated _Nonnull.
57  if (!MCall->isInstanceMessage())
58  return true;
59 
60  // Alternatively, the analyzer could know that the receiver is not null.
61  SVal Receiver = MCall->getReceiverSVal();
62  ConditionTruthVal TV = C.getState()->isNonNull(Receiver);
63  if (TV.isConstrainedTrue())
64  return true;
65 
66  return false;
67  }
68 
69 public:
70  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
71  // Only trust annotations for system headers for non-protocols.
72  if (!Call.isInSystemHeader())
73  return;
74 
76 
77  if (isNonNullPtr(Call, C))
78  if (auto L = Call.getReturnValue().getAs<Loc>())
79  State = State->assume(*L, /*Assumption=*/true);
80 
81  C.addTransition(State);
82  }
83 };
84 
85 } // end empty namespace
86 
87 
88 void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
89  Mgr.registerChecker<TrustNonnullChecker>();
90 }
A (possibly-)qualified type.
Definition: Type.h:655
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
LineState State
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:345
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to &#39;true&#39;.
bool isInSystemHeader() const
Returns true if the callee is known to be from a system header.
Definition: CallEvent.h:261
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
CHECKER * registerChecker(AT... Args)
Used to register checkers.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
bool isAnyPointerType() const
Definition: Type.h:6117
Dataflow Directional Tag Classes.
Nullability getNullabilityAnnotation(QualType Type)
Get nullability annotation for a given type.
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:165
const ProgramStateRef & getState() const
QualType getResultType() const
Returns the result type, adjusted for references.
Definition: CallEvent.cpp:70