ExprEngineObjC.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //=-- ExprEngineObjC.cpp - ExprEngine support for Objective-C ---*- 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 file defines ExprEngine's support for Objective-C expressions.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/AST/StmtObjC.h"
  13. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  16. using namespace clang;
  17. using namespace ento;
  18. void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
  19. ExplodedNode *Pred,
  20. ExplodedNodeSet &Dst) {
  21. ProgramStateRef state = Pred->getState();
  22. const LocationContext *LCtx = Pred->getLocationContext();
  23. SVal baseVal = state->getSVal(Ex->getBase(), LCtx);
  24. SVal location = state->getLValue(Ex->getDecl(), baseVal);
  25. ExplodedNodeSet dstIvar;
  26. StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx);
  27. Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location));
  28. // Perform the post-condition check of the ObjCIvarRefExpr and store
  29. // the created nodes in 'Dst'.
  30. getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
  31. }
  32. void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
  33. ExplodedNode *Pred,
  34. ExplodedNodeSet &Dst) {
  35. getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
  36. }
  37. /// Generate a node in \p Bldr for an iteration statement using ObjC
  38. /// for-loop iterator.
  39. static void populateObjCForDestinationSet(
  40. ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder,
  41. const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV,
  42. SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx,
  43. StmtNodeBuilder &Bldr, bool hasElements) {
  44. for (ExplodedNode *Pred : dstLocation) {
  45. ProgramStateRef state = Pred->getState();
  46. const LocationContext *LCtx = Pred->getLocationContext();
  47. ProgramStateRef nextState =
  48. ExprEngine::setWhetherHasMoreIteration(state, S, LCtx, hasElements);
  49. if (auto MV = elementV.getAs<loc::MemRegionVal>())
  50. if (const auto *R = dyn_cast<TypedValueRegion>(MV->getRegion())) {
  51. // FIXME: The proper thing to do is to really iterate over the
  52. // container. We will do this with dispatch logic to the store.
  53. // For now, just 'conjure' up a symbolic value.
  54. QualType T = R->getValueType();
  55. assert(Loc::isLocType(T));
  56. SVal V;
  57. if (hasElements) {
  58. SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T,
  59. currBldrCtx->blockCount());
  60. V = svalBuilder.makeLoc(Sym);
  61. } else {
  62. V = svalBuilder.makeIntVal(0, T);
  63. }
  64. nextState = nextState->bindLoc(elementV, V, LCtx);
  65. }
  66. Bldr.generateNode(S, Pred, nextState);
  67. }
  68. }
  69. void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
  70. ExplodedNode *Pred,
  71. ExplodedNodeSet &Dst) {
  72. // ObjCForCollectionStmts are processed in two places. This method
  73. // handles the case where an ObjCForCollectionStmt* occurs as one of the
  74. // statements within a basic block. This transfer function does two things:
  75. //
  76. // (1) binds the next container value to 'element'. This creates a new
  77. // node in the ExplodedGraph.
  78. //
  79. // (2) note whether the collection has any more elements (or in other words,
  80. // whether the loop has more iterations). This will be tested in
  81. // processBranch.
  82. //
  83. // FIXME: Eventually this logic should actually do dispatches to
  84. // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
  85. // This will require simulating a temporary NSFastEnumerationState, either
  86. // through an SVal or through the use of MemRegions. This value can
  87. // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
  88. // terminates we reclaim the temporary (it goes out of scope) and we
  89. // we can test if the SVal is 0 or if the MemRegion is null (depending
  90. // on what approach we take).
  91. //
  92. // For now: simulate (1) by assigning either a symbol or nil if the
  93. // container is empty. Thus this transfer function will by default
  94. // result in state splitting.
  95. const Stmt *elem = S->getElement();
  96. const Stmt *collection = S->getCollection();
  97. ProgramStateRef state = Pred->getState();
  98. SVal collectionV = state->getSVal(collection, Pred->getLocationContext());
  99. SVal elementV;
  100. if (const auto *DS = dyn_cast<DeclStmt>(elem)) {
  101. const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
  102. assert(elemD->getInit() == nullptr);
  103. elementV = state->getLValue(elemD, Pred->getLocationContext());
  104. } else {
  105. elementV = state->getSVal(elem, Pred->getLocationContext());
  106. }
  107. bool isContainerNull = state->isNull(collectionV).isConstrainedTrue();
  108. ExplodedNodeSet dstLocation;
  109. evalLocation(dstLocation, S, elem, Pred, state, elementV, false);
  110. ExplodedNodeSet Tmp;
  111. StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
  112. if (!isContainerNull)
  113. populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
  114. SymMgr, currBldrCtx, Bldr,
  115. /*hasElements=*/true);
  116. populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV,
  117. SymMgr, currBldrCtx, Bldr,
  118. /*hasElements=*/false);
  119. // Finally, run any custom checkers.
  120. // FIXME: Eventually all pre- and post-checks should live in VisitStmt.
  121. getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
  122. }
  123. void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
  124. ExplodedNode *Pred,
  125. ExplodedNodeSet &Dst) {
  126. CallEventManager &CEMgr = getStateManager().getCallEventManager();
  127. CallEventRef<ObjCMethodCall> Msg =
  128. CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext());
  129. // There are three cases for the receiver:
  130. // (1) it is definitely nil,
  131. // (2) it is definitely non-nil, and
  132. // (3) we don't know.
  133. //
  134. // If the receiver is definitely nil, we skip the pre/post callbacks and
  135. // instead call the ObjCMessageNil callbacks and return.
  136. //
  137. // If the receiver is definitely non-nil, we call the pre- callbacks,
  138. // evaluate the call, and call the post- callbacks.
  139. //
  140. // If we don't know, we drop the potential nil flow and instead
  141. // continue from the assumed non-nil state as in (2). This approach
  142. // intentionally drops coverage in order to prevent false alarms
  143. // in the following scenario:
  144. //
  145. // id result = [o someMethod]
  146. // if (result) {
  147. // if (!o) {
  148. // // <-- This program point should be unreachable because if o is nil
  149. // // it must the case that result is nil as well.
  150. // }
  151. // }
  152. //
  153. // We could avoid dropping coverage by performing an explicit case split
  154. // on each method call -- but this would get very expensive. An alternative
  155. // would be to introduce lazy constraints.
  156. // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
  157. // Revisit once we have lazier constraints.
  158. if (Msg->isInstanceMessage()) {
  159. SVal recVal = Msg->getReceiverSVal();
  160. if (!recVal.isUndef()) {
  161. // Bifurcate the state into nil and non-nil ones.
  162. DefinedOrUnknownSVal receiverVal =
  163. recVal.castAs<DefinedOrUnknownSVal>();
  164. ProgramStateRef State = Pred->getState();
  165. ProgramStateRef notNilState, nilState;
  166. std::tie(notNilState, nilState) = State->assume(receiverVal);
  167. // Receiver is definitely nil, so run ObjCMessageNil callbacks and return.
  168. if (nilState && !notNilState) {
  169. ExplodedNodeSet dstNil;
  170. StmtNodeBuilder Bldr(Pred, dstNil, *currBldrCtx);
  171. bool HasTag = Pred->getLocation().getTag();
  172. Pred = Bldr.generateNode(ME, Pred, nilState, nullptr,
  173. ProgramPoint::PreStmtKind);
  174. assert((Pred || HasTag) && "Should have cached out already!");
  175. (void)HasTag;
  176. if (!Pred)
  177. return;
  178. ExplodedNodeSet dstPostCheckers;
  179. getCheckerManager().runCheckersForObjCMessageNil(dstPostCheckers, Pred,
  180. *Msg, *this);
  181. for (auto I : dstPostCheckers)
  182. finishArgumentConstruction(Dst, I, *Msg);
  183. return;
  184. }
  185. ExplodedNodeSet dstNonNil;
  186. StmtNodeBuilder Bldr(Pred, dstNonNil, *currBldrCtx);
  187. // Generate a transition to the non-nil state, dropping any potential
  188. // nil flow.
  189. if (notNilState != State) {
  190. bool HasTag = Pred->getLocation().getTag();
  191. Pred = Bldr.generateNode(ME, Pred, notNilState);
  192. assert((Pred || HasTag) && "Should have cached out already!");
  193. (void)HasTag;
  194. if (!Pred)
  195. return;
  196. }
  197. }
  198. }
  199. // Handle the previsits checks.
  200. ExplodedNodeSet dstPrevisit;
  201. getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
  202. *Msg, *this);
  203. ExplodedNodeSet dstGenericPrevisit;
  204. getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit,
  205. *Msg, *this);
  206. // Proceed with evaluate the message expression.
  207. ExplodedNodeSet dstEval;
  208. StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx);
  209. for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(),
  210. DE = dstGenericPrevisit.end(); DI != DE; ++DI) {
  211. ExplodedNode *Pred = *DI;
  212. ProgramStateRef State = Pred->getState();
  213. CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State);
  214. if (UpdatedMsg->isInstanceMessage()) {
  215. SVal recVal = UpdatedMsg->getReceiverSVal();
  216. if (!recVal.isUndef()) {
  217. if (ObjCNoRet.isImplicitNoReturn(ME)) {
  218. // If we raise an exception, for now treat it as a sink.
  219. // Eventually we will want to handle exceptions properly.
  220. Bldr.generateSink(ME, Pred, State);
  221. continue;
  222. }
  223. }
  224. } else {
  225. // Check for special class methods that are known to not return
  226. // and that we should treat as a sink.
  227. if (ObjCNoRet.isImplicitNoReturn(ME)) {
  228. // If we raise an exception, for now treat it as a sink.
  229. // Eventually we will want to handle exceptions properly.
  230. Bldr.generateSink(ME, Pred, Pred->getState());
  231. continue;
  232. }
  233. }
  234. defaultEvalCall(Bldr, Pred, *UpdatedMsg);
  235. }
  236. // If there were constructors called for object-type arguments, clean them up.
  237. ExplodedNodeSet dstArgCleanup;
  238. for (auto I : dstEval)
  239. finishArgumentConstruction(dstArgCleanup, I, *Msg);
  240. ExplodedNodeSet dstPostvisit;
  241. getCheckerManager().runCheckersForPostCall(dstPostvisit, dstArgCleanup,
  242. *Msg, *this);
  243. // Finally, perform the post-condition check of the ObjCMessageExpr and store
  244. // the created nodes in 'Dst'.
  245. getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit,
  246. *Msg, *this);
  247. }