TrustNonnullChecker.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. //== TrustNonnullChecker.cpp --------- API nullability modeling -*- C++ -*--==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This checker adds nullability-related assumptions:
  10. //
  11. // 1. Methods annotated with _Nonnull
  12. // which come from system headers actually return a non-null pointer.
  13. //
  14. // 2. NSDictionary key is non-null after the keyword subscript operation
  15. // on read if and only if the resulting expression is non-null.
  16. //
  17. // 3. NSMutableDictionary index is non-null after a write operation.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  21. #include "clang/Analysis/SelectorExtras.h"
  22. #include "clang/StaticAnalyzer/Core/Checker.h"
  23. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  25. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
  26. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  27. using namespace clang;
  28. using namespace ento;
  29. /// Records implications between symbols.
  30. /// The semantics is:
  31. /// (antecedent != 0) => (consequent != 0)
  32. /// These implications are then read during the evaluation of the assumption,
  33. /// and the appropriate antecedents are applied.
  34. REGISTER_MAP_WITH_PROGRAMSTATE(NonNullImplicationMap, SymbolRef, SymbolRef)
  35. /// The semantics is:
  36. /// (antecedent == 0) => (consequent == 0)
  37. REGISTER_MAP_WITH_PROGRAMSTATE(NullImplicationMap, SymbolRef, SymbolRef)
  38. namespace {
  39. class TrustNonnullChecker : public Checker<check::PostCall,
  40. check::PostObjCMessage,
  41. check::DeadSymbols,
  42. eval::Assume> {
  43. // Do not try to iterate over symbols with higher complexity.
  44. static unsigned constexpr ComplexityThreshold = 10;
  45. Selector ObjectForKeyedSubscriptSel;
  46. Selector ObjectForKeySel;
  47. Selector SetObjectForKeyedSubscriptSel;
  48. Selector SetObjectForKeySel;
  49. public:
  50. TrustNonnullChecker(ASTContext &Ctx)
  51. : ObjectForKeyedSubscriptSel(
  52. getKeywordSelector(Ctx, "objectForKeyedSubscript")),
  53. ObjectForKeySel(getKeywordSelector(Ctx, "objectForKey")),
  54. SetObjectForKeyedSubscriptSel(
  55. getKeywordSelector(Ctx, "setObject", "forKeyedSubscript")),
  56. SetObjectForKeySel(getKeywordSelector(Ctx, "setObject", "forKey")) {}
  57. ProgramStateRef evalAssume(ProgramStateRef State,
  58. SVal Cond,
  59. bool Assumption) const {
  60. const SymbolRef CondS = Cond.getAsSymbol();
  61. if (!CondS || CondS->computeComplexity() > ComplexityThreshold)
  62. return State;
  63. for (auto B=CondS->symbol_begin(), E=CondS->symbol_end(); B != E; ++B) {
  64. const SymbolRef Antecedent = *B;
  65. State = addImplication(Antecedent, State, true);
  66. State = addImplication(Antecedent, State, false);
  67. }
  68. return State;
  69. }
  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. ProgramStateRef State = C.getState();
  75. if (isNonNullPtr(Call, C))
  76. if (auto L = Call.getReturnValue().getAs<Loc>())
  77. State = State->assume(*L, /*assumption=*/true);
  78. C.addTransition(State);
  79. }
  80. void checkPostObjCMessage(const ObjCMethodCall &Msg,
  81. CheckerContext &C) const {
  82. const ObjCInterfaceDecl *ID = Msg.getReceiverInterface();
  83. if (!ID)
  84. return;
  85. ProgramStateRef State = C.getState();
  86. // Index to setter for NSMutableDictionary is assumed to be non-null,
  87. // as an exception is thrown otherwise.
  88. if (interfaceHasSuperclass(ID, "NSMutableDictionary") &&
  89. (Msg.getSelector() == SetObjectForKeyedSubscriptSel ||
  90. Msg.getSelector() == SetObjectForKeySel)) {
  91. if (auto L = Msg.getArgSVal(1).getAs<Loc>())
  92. State = State->assume(*L, /*assumption=*/true);
  93. }
  94. // Record an implication: index is non-null if the output is non-null.
  95. if (interfaceHasSuperclass(ID, "NSDictionary") &&
  96. (Msg.getSelector() == ObjectForKeyedSubscriptSel ||
  97. Msg.getSelector() == ObjectForKeySel)) {
  98. SymbolRef ArgS = Msg.getArgSVal(0).getAsSymbol();
  99. SymbolRef RetS = Msg.getReturnValue().getAsSymbol();
  100. if (ArgS && RetS) {
  101. // Emulate an implication: the argument is non-null if
  102. // the return value is non-null.
  103. State = State->set<NonNullImplicationMap>(RetS, ArgS);
  104. // Conversely, when the argument is null, the return value
  105. // is definitely null.
  106. State = State->set<NullImplicationMap>(ArgS, RetS);
  107. }
  108. }
  109. C.addTransition(State);
  110. }
  111. void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const {
  112. ProgramStateRef State = C.getState();
  113. State = dropDeadFromGDM<NullImplicationMap>(SymReaper, State);
  114. State = dropDeadFromGDM<NonNullImplicationMap>(SymReaper, State);
  115. C.addTransition(State);
  116. }
  117. private:
  118. /// \returns State with GDM \p MapName where all dead symbols were
  119. // removed.
  120. template <typename MapName>
  121. ProgramStateRef dropDeadFromGDM(SymbolReaper &SymReaper,
  122. ProgramStateRef State) const {
  123. for (const std::pair<SymbolRef, SymbolRef> &P : State->get<MapName>())
  124. if (!SymReaper.isLive(P.first) || !SymReaper.isLive(P.second))
  125. State = State->remove<MapName>(P.first);
  126. return State;
  127. }
  128. /// \returns Whether we trust the result of the method call to be
  129. /// a non-null pointer.
  130. bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
  131. QualType ExprRetType = Call.getResultType();
  132. if (!ExprRetType->isAnyPointerType())
  133. return false;
  134. if (getNullabilityAnnotation(ExprRetType) == Nullability::Nonnull)
  135. return true;
  136. // The logic for ObjC instance method calls is more complicated,
  137. // as the return value is nil when the receiver is nil.
  138. if (!isa<ObjCMethodCall>(&Call))
  139. return false;
  140. const auto *MCall = cast<ObjCMethodCall>(&Call);
  141. const ObjCMethodDecl *MD = MCall->getDecl();
  142. // Distrust protocols.
  143. if (isa<ObjCProtocolDecl>(MD->getDeclContext()))
  144. return false;
  145. QualType DeclRetType = MD->getReturnType();
  146. if (getNullabilityAnnotation(DeclRetType) != Nullability::Nonnull)
  147. return false;
  148. // For class messages it is sufficient for the declaration to be
  149. // annotated _Nonnull.
  150. if (!MCall->isInstanceMessage())
  151. return true;
  152. // Alternatively, the analyzer could know that the receiver is not null.
  153. SVal Receiver = MCall->getReceiverSVal();
  154. ConditionTruthVal TV = C.getState()->isNonNull(Receiver);
  155. if (TV.isConstrainedTrue())
  156. return true;
  157. return false;
  158. }
  159. /// \return Whether \p ID has a superclass by the name \p ClassName.
  160. bool interfaceHasSuperclass(const ObjCInterfaceDecl *ID,
  161. StringRef ClassName) const {
  162. if (ID->getIdentifier()->getName() == ClassName)
  163. return true;
  164. if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
  165. return interfaceHasSuperclass(Super, ClassName);
  166. return false;
  167. }
  168. /// \return a state with an optional implication added (if exists)
  169. /// from a map of recorded implications.
  170. /// If \p Negated is true, checks NullImplicationMap, and assumes
  171. /// the negation of \p Antecedent.
  172. /// Checks NonNullImplicationMap and assumes \p Antecedent otherwise.
  173. ProgramStateRef addImplication(SymbolRef Antecedent,
  174. ProgramStateRef InputState,
  175. bool Negated) const {
  176. if (!InputState)
  177. return nullptr;
  178. SValBuilder &SVB = InputState->getStateManager().getSValBuilder();
  179. const SymbolRef *Consequent =
  180. Negated ? InputState->get<NonNullImplicationMap>(Antecedent)
  181. : InputState->get<NullImplicationMap>(Antecedent);
  182. if (!Consequent)
  183. return InputState;
  184. SVal AntecedentV = SVB.makeSymbolVal(Antecedent);
  185. ProgramStateRef State = InputState;
  186. if ((Negated && InputState->isNonNull(AntecedentV).isConstrainedTrue())
  187. || (!Negated && InputState->isNull(AntecedentV).isConstrainedTrue())) {
  188. SVal ConsequentS = SVB.makeSymbolVal(*Consequent);
  189. State = InputState->assume(ConsequentS.castAs<DefinedSVal>(), Negated);
  190. if (!State)
  191. return nullptr;
  192. // Drop implications from the map.
  193. if (Negated) {
  194. State = State->remove<NonNullImplicationMap>(Antecedent);
  195. State = State->remove<NullImplicationMap>(*Consequent);
  196. } else {
  197. State = State->remove<NullImplicationMap>(Antecedent);
  198. State = State->remove<NonNullImplicationMap>(*Consequent);
  199. }
  200. }
  201. return State;
  202. }
  203. };
  204. } // end empty namespace
  205. void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
  206. Mgr.registerChecker<TrustNonnullChecker>(Mgr.getASTContext());
  207. }
  208. bool ento::shouldRegisterTrustNonnullChecker(const CheckerManager &mgr) {
  209. return true;
  210. }