DynamicTypePropagation.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. //===- DynamicTypePropagation.cpp ------------------------------*- 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 file contains two checkers. One helps the static analyzer core to track
  11. // types, the other does type inference on Obj-C generics and report type
  12. // errors.
  13. //
  14. // Dynamic Type Propagation:
  15. // This checker defines the rules for dynamic type gathering and propagation.
  16. //
  17. // Generics Checker for Objective-C:
  18. // This checker tries to find type errors that the compiler is not able to catch
  19. // due to the implicit conversions that were introduced for backward
  20. // compatibility.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. #include "ClangSACheckers.h"
  24. #include "clang/AST/ParentMap.h"
  25. #include "clang/AST/RecursiveASTVisitor.h"
  26. #include "clang/Basic/Builtins.h"
  27. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  28. #include "clang/StaticAnalyzer/Core/Checker.h"
  29. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  30. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  31. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
  32. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  33. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
  34. using namespace clang;
  35. using namespace ento;
  36. // ProgramState trait - The type inflation is tracked by DynamicTypeMap. This is
  37. // an auxiliary map that tracks more information about generic types, because in
  38. // some cases the most derived type is not the most informative one about the
  39. // type parameters. This types that are stored for each symbol in this map must
  40. // be specialized.
  41. // TODO: In some case the type stored in this map is exactly the same that is
  42. // stored in DynamicTypeMap. We should no store duplicated information in those
  43. // cases.
  44. REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
  45. const ObjCObjectPointerType *)
  46. namespace {
  47. class DynamicTypePropagation:
  48. public Checker< check::PreCall,
  49. check::PostCall,
  50. check::DeadSymbols,
  51. check::PostStmt<CastExpr>,
  52. check::PostStmt<CXXNewExpr>,
  53. check::PreObjCMessage,
  54. check::PostObjCMessage > {
  55. const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
  56. CheckerContext &C) const;
  57. /// \brief Return a better dynamic type if one can be derived from the cast.
  58. const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
  59. CheckerContext &C) const;
  60. ExplodedNode *dynamicTypePropagationOnCasts(const CastExpr *CE,
  61. ProgramStateRef &State,
  62. CheckerContext &C) const;
  63. mutable std::unique_ptr<BugType> ObjCGenericsBugType;
  64. void initBugType() const {
  65. if (!ObjCGenericsBugType)
  66. ObjCGenericsBugType.reset(
  67. new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
  68. }
  69. class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
  70. public:
  71. GenericsBugVisitor(SymbolRef S) : Sym(S) {}
  72. void Profile(llvm::FoldingSetNodeID &ID) const override {
  73. static int X = 0;
  74. ID.AddPointer(&X);
  75. ID.AddPointer(Sym);
  76. }
  77. std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
  78. const ExplodedNode *PrevN,
  79. BugReporterContext &BRC,
  80. BugReport &BR) override;
  81. private:
  82. // The tracked symbol.
  83. SymbolRef Sym;
  84. };
  85. void reportGenericsBug(const ObjCObjectPointerType *From,
  86. const ObjCObjectPointerType *To, ExplodedNode *N,
  87. SymbolRef Sym, CheckerContext &C,
  88. const Stmt *ReportedNode = nullptr) const;
  89. public:
  90. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  91. void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  92. void checkPostStmt(const CastExpr *CastE, CheckerContext &C) const;
  93. void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
  94. void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
  95. void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  96. void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  97. /// This value is set to true, when the Generics checker is turned on.
  98. DefaultBool CheckGenerics;
  99. };
  100. } // end anonymous namespace
  101. void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
  102. CheckerContext &C) const {
  103. ProgramStateRef State = C.getState();
  104. DynamicTypeMapImpl TypeMap = State->get<DynamicTypeMap>();
  105. for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
  106. I != E; ++I) {
  107. if (!SR.isLiveRegion(I->first)) {
  108. State = State->remove<DynamicTypeMap>(I->first);
  109. }
  110. }
  111. if (!SR.hasDeadSymbols()) {
  112. C.addTransition(State);
  113. return;
  114. }
  115. MostSpecializedTypeArgsMapTy TyArgMap =
  116. State->get<MostSpecializedTypeArgsMap>();
  117. for (MostSpecializedTypeArgsMapTy::iterator I = TyArgMap.begin(),
  118. E = TyArgMap.end();
  119. I != E; ++I) {
  120. if (SR.isDead(I->first)) {
  121. State = State->remove<MostSpecializedTypeArgsMap>(I->first);
  122. }
  123. }
  124. C.addTransition(State);
  125. }
  126. static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
  127. CheckerContext &C) {
  128. assert(Region);
  129. assert(MD);
  130. ASTContext &Ctx = C.getASTContext();
  131. QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
  132. ProgramStateRef State = C.getState();
  133. State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubclass=*/false);
  134. C.addTransition(State);
  135. }
  136. void DynamicTypePropagation::checkPreCall(const CallEvent &Call,
  137. CheckerContext &C) const {
  138. if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
  139. // C++11 [class.cdtor]p4: When a virtual function is called directly or
  140. // indirectly from a constructor or from a destructor, including during
  141. // the construction or destruction of the class's non-static data members,
  142. // and the object to which the call applies is the object under
  143. // construction or destruction, the function called is the final overrider
  144. // in the constructor's or destructor's class and not one overriding it in
  145. // a more-derived class.
  146. switch (Ctor->getOriginExpr()->getConstructionKind()) {
  147. case CXXConstructExpr::CK_Complete:
  148. case CXXConstructExpr::CK_Delegating:
  149. // No additional type info necessary.
  150. return;
  151. case CXXConstructExpr::CK_NonVirtualBase:
  152. case CXXConstructExpr::CK_VirtualBase:
  153. if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
  154. recordFixedType(Target, Ctor->getDecl(), C);
  155. return;
  156. }
  157. return;
  158. }
  159. if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) {
  160. // C++11 [class.cdtor]p4 (see above)
  161. if (!Dtor->isBaseDestructor())
  162. return;
  163. const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
  164. if (!Target)
  165. return;
  166. const Decl *D = Dtor->getDecl();
  167. if (!D)
  168. return;
  169. recordFixedType(Target, cast<CXXDestructorDecl>(D), C);
  170. return;
  171. }
  172. }
  173. void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
  174. CheckerContext &C) const {
  175. // We can obtain perfect type info for return values from some calls.
  176. if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
  177. // Get the returned value if it's a region.
  178. const MemRegion *RetReg = Call.getReturnValue().getAsRegion();
  179. if (!RetReg)
  180. return;
  181. ProgramStateRef State = C.getState();
  182. const ObjCMethodDecl *D = Msg->getDecl();
  183. if (D && D->hasRelatedResultType()) {
  184. switch (Msg->getMethodFamily()) {
  185. default:
  186. break;
  187. // We assume that the type of the object returned by alloc and new are the
  188. // pointer to the object of the class specified in the receiver of the
  189. // message.
  190. case OMF_alloc:
  191. case OMF_new: {
  192. // Get the type of object that will get created.
  193. const ObjCMessageExpr *MsgE = Msg->getOriginExpr();
  194. const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C);
  195. if (!ObjTy)
  196. return;
  197. QualType DynResTy =
  198. C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
  199. C.addTransition(setDynamicTypeInfo(State, RetReg, DynResTy, false));
  200. break;
  201. }
  202. case OMF_init: {
  203. // Assume, the result of the init method has the same dynamic type as
  204. // the receiver and propagate the dynamic type info.
  205. const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
  206. if (!RecReg)
  207. return;
  208. DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg);
  209. C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType));
  210. break;
  211. }
  212. }
  213. }
  214. return;
  215. }
  216. if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
  217. // We may need to undo the effects of our pre-call check.
  218. switch (Ctor->getOriginExpr()->getConstructionKind()) {
  219. case CXXConstructExpr::CK_Complete:
  220. case CXXConstructExpr::CK_Delegating:
  221. // No additional work necessary.
  222. // Note: This will leave behind the actual type of the object for
  223. // complete constructors, but arguably that's a good thing, since it
  224. // means the dynamic type info will be correct even for objects
  225. // constructed with operator new.
  226. return;
  227. case CXXConstructExpr::CK_NonVirtualBase:
  228. case CXXConstructExpr::CK_VirtualBase:
  229. if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
  230. // We just finished a base constructor. Now we can use the subclass's
  231. // type when resolving virtual calls.
  232. const LocationContext *LCtx = C.getLocationContext();
  233. // FIXME: In C++17 classes with non-virtual bases may be treated as
  234. // aggregates, and in such case no top-frame constructor will be called.
  235. // Figure out if we need to do anything in this case.
  236. // FIXME: Instead of relying on the ParentMap, we should have the
  237. // trigger-statement (InitListExpr in this case) available in this
  238. // callback, ideally as part of CallEvent.
  239. if (dyn_cast_or_null<InitListExpr>(
  240. LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
  241. return;
  242. recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
  243. }
  244. return;
  245. }
  246. }
  247. }
  248. /// TODO: Handle explicit casts.
  249. /// Handle C++ casts.
  250. ///
  251. /// Precondition: the cast is between ObjCObjectPointers.
  252. ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
  253. const CastExpr *CE, ProgramStateRef &State, CheckerContext &C) const {
  254. // We only track type info for regions.
  255. const MemRegion *ToR = C.getSVal(CE).getAsRegion();
  256. if (!ToR)
  257. return C.getPredecessor();
  258. if (isa<ExplicitCastExpr>(CE))
  259. return C.getPredecessor();
  260. if (const Type *NewTy = getBetterObjCType(CE, C)) {
  261. State = setDynamicTypeInfo(State, ToR, QualType(NewTy, 0));
  262. return C.addTransition(State);
  263. }
  264. return C.getPredecessor();
  265. }
  266. void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
  267. CheckerContext &C) const {
  268. if (NewE->isArray())
  269. return;
  270. // We only track dynamic type info for regions.
  271. const MemRegion *MR = C.getSVal(NewE).getAsRegion();
  272. if (!MR)
  273. return;
  274. C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(),
  275. /*CanBeSubclass=*/false));
  276. }
  277. const ObjCObjectType *
  278. DynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
  279. CheckerContext &C) const {
  280. if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) {
  281. if (const ObjCObjectType *ObjTy
  282. = MsgE->getClassReceiver()->getAs<ObjCObjectType>())
  283. return ObjTy;
  284. }
  285. if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) {
  286. if (const ObjCObjectType *ObjTy
  287. = MsgE->getSuperType()->getAs<ObjCObjectType>())
  288. return ObjTy;
  289. }
  290. const Expr *RecE = MsgE->getInstanceReceiver();
  291. if (!RecE)
  292. return nullptr;
  293. RecE= RecE->IgnoreParenImpCasts();
  294. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
  295. const StackFrameContext *SFCtx = C.getStackFrame();
  296. // Are we calling [self alloc]? If this is self, get the type of the
  297. // enclosing ObjC class.
  298. if (DRE->getDecl() == SFCtx->getSelfDecl()) {
  299. if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl()))
  300. if (const ObjCObjectType *ObjTy =
  301. dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
  302. return ObjTy;
  303. }
  304. }
  305. return nullptr;
  306. }
  307. // Return a better dynamic type if one can be derived from the cast.
  308. // Compare the current dynamic type of the region and the new type to which we
  309. // are casting. If the new type is lower in the inheritance hierarchy, pick it.
  310. const ObjCObjectPointerType *
  311. DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
  312. CheckerContext &C) const {
  313. const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
  314. assert(ToR);
  315. // Get the old and new types.
  316. const ObjCObjectPointerType *NewTy =
  317. CastE->getType()->getAs<ObjCObjectPointerType>();
  318. if (!NewTy)
  319. return nullptr;
  320. QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType();
  321. if (OldDTy.isNull()) {
  322. return NewTy;
  323. }
  324. const ObjCObjectPointerType *OldTy =
  325. OldDTy->getAs<ObjCObjectPointerType>();
  326. if (!OldTy)
  327. return nullptr;
  328. // Id the old type is 'id', the new one is more precise.
  329. if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
  330. return NewTy;
  331. // Return new if it's a subclass of old.
  332. const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
  333. const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
  334. if (ToI && FromI && FromI->isSuperClassOf(ToI))
  335. return NewTy;
  336. return nullptr;
  337. }
  338. static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
  339. const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
  340. const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
  341. // Checking if from and to are the same classes modulo specialization.
  342. if (From->getInterfaceDecl()->getCanonicalDecl() ==
  343. To->getInterfaceDecl()->getCanonicalDecl()) {
  344. if (To->isSpecialized()) {
  345. assert(MostInformativeCandidate->isSpecialized());
  346. return MostInformativeCandidate;
  347. }
  348. return From;
  349. }
  350. if (To->getObjectType()->getSuperClassType().isNull()) {
  351. // If To has no super class and From and To aren't the same then
  352. // To was not actually a descendent of From. In this case the best we can
  353. // do is 'From'.
  354. return From;
  355. }
  356. const auto *SuperOfTo =
  357. To->getObjectType()->getSuperClassType()->getAs<ObjCObjectType>();
  358. assert(SuperOfTo);
  359. QualType SuperPtrOfToQual =
  360. C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
  361. const auto *SuperPtrOfTo = SuperPtrOfToQual->getAs<ObjCObjectPointerType>();
  362. if (To->isUnspecialized())
  363. return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
  364. C);
  365. else
  366. return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
  367. MostInformativeCandidate, C);
  368. }
  369. /// A downcast may loose specialization information. E. g.:
  370. /// MutableMap<T, U> : Map
  371. /// The downcast to MutableMap looses the information about the types of the
  372. /// Map (due to the type parameters are not being forwarded to Map), and in
  373. /// general there is no way to recover that information from the
  374. /// declaration. In order to have to most information, lets find the most
  375. /// derived type that has all the type parameters forwarded.
  376. ///
  377. /// Get the a subclass of \p From (which has a lower bound \p To) that do not
  378. /// loose information about type parameters. \p To has to be a subclass of
  379. /// \p From. From has to be specialized.
  380. static const ObjCObjectPointerType *
  381. getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
  382. const ObjCObjectPointerType *To, ASTContext &C) {
  383. return getMostInformativeDerivedClassImpl(From, To, To, C);
  384. }
  385. /// Inputs:
  386. /// \param StaticLowerBound Static lower bound for a symbol. The dynamic lower
  387. /// bound might be the subclass of this type.
  388. /// \param StaticUpperBound A static upper bound for a symbol.
  389. /// \p StaticLowerBound expected to be the subclass of \p StaticUpperBound.
  390. /// \param Current The type that was inferred for a symbol in a previous
  391. /// context. Might be null when this is the first time that inference happens.
  392. /// Precondition:
  393. /// \p StaticLowerBound or \p StaticUpperBound is specialized. If \p Current
  394. /// is not null, it is specialized.
  395. /// Possible cases:
  396. /// (1) The \p Current is null and \p StaticLowerBound <: \p StaticUpperBound
  397. /// (2) \p StaticLowerBound <: \p Current <: \p StaticUpperBound
  398. /// (3) \p Current <: \p StaticLowerBound <: \p StaticUpperBound
  399. /// (4) \p StaticLowerBound <: \p StaticUpperBound <: \p Current
  400. /// Effect:
  401. /// Use getMostInformativeDerivedClass with the upper and lower bound of the
  402. /// set {\p StaticLowerBound, \p Current, \p StaticUpperBound}. The computed
  403. /// lower bound must be specialized. If the result differs from \p Current or
  404. /// \p Current is null, store the result.
  405. static bool
  406. storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
  407. const ObjCObjectPointerType *const *Current,
  408. const ObjCObjectPointerType *StaticLowerBound,
  409. const ObjCObjectPointerType *StaticUpperBound,
  410. ASTContext &C) {
  411. // TODO: The above 4 cases are not exhaustive. In particular, it is possible
  412. // for Current to be incomparable with StaticLowerBound, StaticUpperBound,
  413. // or both.
  414. //
  415. // For example, suppose Foo<T> and Bar<T> are unrelated types.
  416. //
  417. // Foo<T> *f = ...
  418. // Bar<T> *b = ...
  419. //
  420. // id t1 = b;
  421. // f = t1;
  422. // id t2 = f; // StaticLowerBound is Foo<T>, Current is Bar<T>
  423. //
  424. // We should either constrain the callers of this function so that the stated
  425. // preconditions hold (and assert it) or rewrite the function to expicitly
  426. // handle the additional cases.
  427. // Precondition
  428. assert(StaticUpperBound->isSpecialized() ||
  429. StaticLowerBound->isSpecialized());
  430. assert(!Current || (*Current)->isSpecialized());
  431. // Case (1)
  432. if (!Current) {
  433. if (StaticUpperBound->isUnspecialized()) {
  434. State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
  435. return true;
  436. }
  437. // Upper bound is specialized.
  438. const ObjCObjectPointerType *WithMostInfo =
  439. getMostInformativeDerivedClass(StaticUpperBound, StaticLowerBound, C);
  440. State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
  441. return true;
  442. }
  443. // Case (3)
  444. if (C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
  445. return false;
  446. }
  447. // Case (4)
  448. if (C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
  449. // The type arguments might not be forwarded at any point of inheritance.
  450. const ObjCObjectPointerType *WithMostInfo =
  451. getMostInformativeDerivedClass(*Current, StaticUpperBound, C);
  452. WithMostInfo =
  453. getMostInformativeDerivedClass(WithMostInfo, StaticLowerBound, C);
  454. if (WithMostInfo == *Current)
  455. return false;
  456. State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
  457. return true;
  458. }
  459. // Case (2)
  460. const ObjCObjectPointerType *WithMostInfo =
  461. getMostInformativeDerivedClass(*Current, StaticLowerBound, C);
  462. if (WithMostInfo != *Current) {
  463. State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
  464. return true;
  465. }
  466. return false;
  467. }
  468. /// Type inference based on static type information that is available for the
  469. /// cast and the tracked type information for the given symbol. When the tracked
  470. /// symbol and the destination type of the cast are unrelated, report an error.
  471. void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
  472. CheckerContext &C) const {
  473. if (CE->getCastKind() != CK_BitCast)
  474. return;
  475. QualType OriginType = CE->getSubExpr()->getType();
  476. QualType DestType = CE->getType();
  477. const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
  478. const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
  479. if (!OrigObjectPtrType || !DestObjectPtrType)
  480. return;
  481. ProgramStateRef State = C.getState();
  482. ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
  483. ASTContext &ASTCtxt = C.getASTContext();
  484. // This checker detects the subtyping relationships using the assignment
  485. // rules. In order to be able to do this the kindofness must be stripped
  486. // first. The checker treats every type as kindof type anyways: when the
  487. // tracked type is the subtype of the static type it tries to look up the
  488. // methods in the tracked type first.
  489. OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
  490. DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
  491. if (OrigObjectPtrType->isUnspecialized() &&
  492. DestObjectPtrType->isUnspecialized())
  493. return;
  494. SymbolRef Sym = C.getSVal(CE).getAsSymbol();
  495. if (!Sym)
  496. return;
  497. const ObjCObjectPointerType *const *TrackedType =
  498. State->get<MostSpecializedTypeArgsMap>(Sym);
  499. if (isa<ExplicitCastExpr>(CE)) {
  500. // Treat explicit casts as an indication from the programmer that the
  501. // Objective-C type system is not rich enough to express the needed
  502. // invariant. In such cases, forget any existing information inferred
  503. // about the type arguments. We don't assume the casted-to specialized
  504. // type here because the invariant the programmer specifies in the cast
  505. // may only hold at this particular program point and not later ones.
  506. // We don't want a suppressing cast to require a cascade of casts down the
  507. // line.
  508. if (TrackedType) {
  509. State = State->remove<MostSpecializedTypeArgsMap>(Sym);
  510. C.addTransition(State, AfterTypeProp);
  511. }
  512. return;
  513. }
  514. // Check which assignments are legal.
  515. bool OrigToDest =
  516. ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
  517. bool DestToOrig =
  518. ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
  519. // The tracked type should be the sub or super class of the static destination
  520. // type. When an (implicit) upcast or a downcast happens according to static
  521. // types, and there is no subtyping relationship between the tracked and the
  522. // static destination types, it indicates an error.
  523. if (TrackedType &&
  524. !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
  525. !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
  526. static CheckerProgramPointTag IllegalConv(this, "IllegalConversion");
  527. ExplodedNode *N = C.addTransition(State, AfterTypeProp, &IllegalConv);
  528. reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
  529. return;
  530. }
  531. // Handle downcasts and upcasts.
  532. const ObjCObjectPointerType *LowerBound = DestObjectPtrType;
  533. const ObjCObjectPointerType *UpperBound = OrigObjectPtrType;
  534. if (OrigToDest && !DestToOrig)
  535. std::swap(LowerBound, UpperBound);
  536. // The id type is not a real bound. Eliminate it.
  537. LowerBound = LowerBound->isObjCIdType() ? UpperBound : LowerBound;
  538. UpperBound = UpperBound->isObjCIdType() ? LowerBound : UpperBound;
  539. if (storeWhenMoreInformative(State, Sym, TrackedType, LowerBound, UpperBound,
  540. ASTCtxt)) {
  541. C.addTransition(State, AfterTypeProp);
  542. }
  543. }
  544. static const Expr *stripCastsAndSugar(const Expr *E) {
  545. E = E->IgnoreParenImpCasts();
  546. if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
  547. E = POE->getSyntacticForm()->IgnoreParenImpCasts();
  548. if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
  549. E = OVE->getSourceExpr()->IgnoreParenImpCasts();
  550. return E;
  551. }
  552. static bool isObjCTypeParamDependent(QualType Type) {
  553. // It is illegal to typedef parameterized types inside an interface. Therfore
  554. // an Objective-C type can only be dependent on a type parameter when the type
  555. // parameter structurally present in the type itself.
  556. class IsObjCTypeParamDependentTypeVisitor
  557. : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
  558. public:
  559. IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
  560. bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) {
  561. if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
  562. Result = true;
  563. return false;
  564. }
  565. return true;
  566. }
  567. bool Result;
  568. };
  569. IsObjCTypeParamDependentTypeVisitor Visitor;
  570. Visitor.TraverseType(Type);
  571. return Visitor.Result;
  572. }
  573. /// A method might not be available in the interface indicated by the static
  574. /// type. However it might be available in the tracked type. In order to
  575. /// properly substitute the type parameters we need the declaration context of
  576. /// the method. The more specialized the enclosing class of the method is, the
  577. /// more likely that the parameter substitution will be successful.
  578. static const ObjCMethodDecl *
  579. findMethodDecl(const ObjCMessageExpr *MessageExpr,
  580. const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
  581. const ObjCMethodDecl *Method = nullptr;
  582. QualType ReceiverType = MessageExpr->getReceiverType();
  583. const auto *ReceiverObjectPtrType =
  584. ReceiverType->getAs<ObjCObjectPointerType>();
  585. // Do this "devirtualization" on instance and class methods only. Trust the
  586. // static type on super and super class calls.
  587. if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
  588. MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
  589. // When the receiver type is id, Class, or some super class of the tracked
  590. // type, look up the method in the tracked type, not in the receiver type.
  591. // This way we preserve more information.
  592. if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
  593. ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType, TrackedType)) {
  594. const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
  595. // The method might not be found.
  596. Selector Sel = MessageExpr->getSelector();
  597. Method = InterfaceDecl->lookupInstanceMethod(Sel);
  598. if (!Method)
  599. Method = InterfaceDecl->lookupClassMethod(Sel);
  600. }
  601. }
  602. // Fallback to statick method lookup when the one based on the tracked type
  603. // failed.
  604. return Method ? Method : MessageExpr->getMethodDecl();
  605. }
  606. /// Get the returned ObjCObjectPointerType by a method based on the tracked type
  607. /// information, or null pointer when the returned type is not an
  608. /// ObjCObjectPointerType.
  609. static QualType getReturnTypeForMethod(
  610. const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs,
  611. const ObjCObjectPointerType *SelfType, ASTContext &C) {
  612. QualType StaticResultType = Method->getReturnType();
  613. // Is the return type declared as instance type?
  614. if (StaticResultType == C.getObjCInstanceType())
  615. return QualType(SelfType, 0);
  616. // Check whether the result type depends on a type parameter.
  617. if (!isObjCTypeParamDependent(StaticResultType))
  618. return QualType();
  619. QualType ResultType = StaticResultType.substObjCTypeArgs(
  620. C, TypeArgs, ObjCSubstitutionContext::Result);
  621. return ResultType;
  622. }
  623. /// When the receiver has a tracked type, use that type to validate the
  624. /// argumments of the message expression and the return value.
  625. void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
  626. CheckerContext &C) const {
  627. ProgramStateRef State = C.getState();
  628. SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
  629. if (!Sym)
  630. return;
  631. const ObjCObjectPointerType *const *TrackedType =
  632. State->get<MostSpecializedTypeArgsMap>(Sym);
  633. if (!TrackedType)
  634. return;
  635. // Get the type arguments from tracked type and substitute type arguments
  636. // before do the semantic check.
  637. ASTContext &ASTCtxt = C.getASTContext();
  638. const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
  639. const ObjCMethodDecl *Method =
  640. findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
  641. // It is possible to call non-existent methods in Obj-C.
  642. if (!Method)
  643. return;
  644. // If the method is declared on a class that has a non-invariant
  645. // type parameter, don't warn about parameter mismatches after performing
  646. // substitution. This prevents warning when the programmer has purposely
  647. // casted the receiver to a super type or unspecialized type but the analyzer
  648. // has a more precise tracked type than the programmer intends at the call
  649. // site.
  650. //
  651. // For example, consider NSArray (which has a covariant type parameter)
  652. // and NSMutableArray (a subclass of NSArray where the type parameter is
  653. // invariant):
  654. // NSMutableArray *a = [[NSMutableArray<NSString *> alloc] init;
  655. //
  656. // [a containsObject:number]; // Safe: -containsObject is defined on NSArray.
  657. // NSArray<NSObject *> *other = [a arrayByAddingObject:number] // Safe
  658. //
  659. // [a addObject:number] // Unsafe: -addObject: is defined on NSMutableArray
  660. //
  661. const ObjCInterfaceDecl *Interface = Method->getClassInterface();
  662. if (!Interface)
  663. return;
  664. ObjCTypeParamList *TypeParams = Interface->getTypeParamList();
  665. if (!TypeParams)
  666. return;
  667. for (ObjCTypeParamDecl *TypeParam : *TypeParams) {
  668. if (TypeParam->getVariance() != ObjCTypeParamVariance::Invariant)
  669. return;
  670. }
  671. Optional<ArrayRef<QualType>> TypeArgs =
  672. (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
  673. // This case might happen when there is an unspecialized override of a
  674. // specialized method.
  675. if (!TypeArgs)
  676. return;
  677. for (unsigned i = 0; i < Method->param_size(); i++) {
  678. const Expr *Arg = MessageExpr->getArg(i);
  679. const ParmVarDecl *Param = Method->parameters()[i];
  680. QualType OrigParamType = Param->getType();
  681. if (!isObjCTypeParamDependent(OrigParamType))
  682. continue;
  683. QualType ParamType = OrigParamType.substObjCTypeArgs(
  684. ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
  685. // Check if it can be assigned
  686. const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
  687. const auto *ArgObjectPtrType =
  688. stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
  689. if (!ParamObjectPtrType || !ArgObjectPtrType)
  690. continue;
  691. // Check if we have more concrete tracked type that is not a super type of
  692. // the static argument type.
  693. SVal ArgSVal = M.getArgSVal(i);
  694. SymbolRef ArgSym = ArgSVal.getAsSymbol();
  695. if (ArgSym) {
  696. const ObjCObjectPointerType *const *TrackedArgType =
  697. State->get<MostSpecializedTypeArgsMap>(ArgSym);
  698. if (TrackedArgType &&
  699. ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
  700. ArgObjectPtrType = *TrackedArgType;
  701. }
  702. }
  703. // Warn when argument is incompatible with the parameter.
  704. if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
  705. ArgObjectPtrType)) {
  706. static CheckerProgramPointTag Tag(this, "ArgTypeMismatch");
  707. ExplodedNode *N = C.addTransition(State, &Tag);
  708. reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
  709. return;
  710. }
  711. }
  712. }
  713. /// This callback is used to infer the types for Class variables. This info is
  714. /// used later to validate messages that sent to classes. Class variables are
  715. /// initialized with by invoking the 'class' method on a class.
  716. /// This method is also used to infer the type information for the return
  717. /// types.
  718. // TODO: right now it only tracks generic types. Extend this to track every
  719. // type in the DynamicTypeMap and diagnose type errors!
  720. void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M,
  721. CheckerContext &C) const {
  722. const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
  723. SymbolRef RetSym = M.getReturnValue().getAsSymbol();
  724. if (!RetSym)
  725. return;
  726. Selector Sel = MessageExpr->getSelector();
  727. ProgramStateRef State = C.getState();
  728. // Inference for class variables.
  729. // We are only interested in cases where the class method is invoked on a
  730. // class. This method is provided by the runtime and available on all classes.
  731. if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Class &&
  732. Sel.getAsString() == "class") {
  733. QualType ReceiverType = MessageExpr->getClassReceiver();
  734. const auto *ReceiverClassType = ReceiverType->getAs<ObjCObjectType>();
  735. QualType ReceiverClassPointerType =
  736. C.getASTContext().getObjCObjectPointerType(
  737. QualType(ReceiverClassType, 0));
  738. if (!ReceiverClassType->isSpecialized())
  739. return;
  740. const auto *InferredType =
  741. ReceiverClassPointerType->getAs<ObjCObjectPointerType>();
  742. assert(InferredType);
  743. State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
  744. C.addTransition(State);
  745. return;
  746. }
  747. // Tracking for return types.
  748. SymbolRef RecSym = M.getReceiverSVal().getAsSymbol();
  749. if (!RecSym)
  750. return;
  751. const ObjCObjectPointerType *const *TrackedType =
  752. State->get<MostSpecializedTypeArgsMap>(RecSym);
  753. if (!TrackedType)
  754. return;
  755. ASTContext &ASTCtxt = C.getASTContext();
  756. const ObjCMethodDecl *Method =
  757. findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
  758. if (!Method)
  759. return;
  760. Optional<ArrayRef<QualType>> TypeArgs =
  761. (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
  762. if (!TypeArgs)
  763. return;
  764. QualType ResultType =
  765. getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt);
  766. // The static type is the same as the deduced type.
  767. if (ResultType.isNull())
  768. return;
  769. const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
  770. ExplodedNode *Pred = C.getPredecessor();
  771. // When there is an entry available for the return symbol in DynamicTypeMap,
  772. // the call was inlined, and the information in the DynamicTypeMap is should
  773. // be precise.
  774. if (RetRegion && !State->get<DynamicTypeMap>(RetRegion)) {
  775. // TODO: we have duplicated information in DynamicTypeMap and
  776. // MostSpecializedTypeArgsMap. We should only store anything in the later if
  777. // the stored data differs from the one stored in the former.
  778. State = setDynamicTypeInfo(State, RetRegion, ResultType,
  779. /*CanBeSubclass=*/true);
  780. Pred = C.addTransition(State);
  781. }
  782. const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
  783. if (!ResultPtrType || ResultPtrType->isUnspecialized())
  784. return;
  785. // When the result is a specialized type and it is not tracked yet, track it
  786. // for the result symbol.
  787. if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
  788. State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
  789. C.addTransition(State, Pred);
  790. }
  791. }
  792. void DynamicTypePropagation::reportGenericsBug(
  793. const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
  794. ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
  795. const Stmt *ReportedNode) const {
  796. if (!CheckGenerics)
  797. return;
  798. initBugType();
  799. SmallString<192> Buf;
  800. llvm::raw_svector_ostream OS(Buf);
  801. OS << "Conversion from value of type '";
  802. QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
  803. OS << "' to incompatible type '";
  804. QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
  805. OS << "'";
  806. std::unique_ptr<BugReport> R(
  807. new BugReport(*ObjCGenericsBugType, OS.str(), N));
  808. R->markInteresting(Sym);
  809. R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
  810. if (ReportedNode)
  811. R->addRange(ReportedNode->getSourceRange());
  812. C.emitReport(std::move(R));
  813. }
  814. std::shared_ptr<PathDiagnosticPiece>
  815. DynamicTypePropagation::GenericsBugVisitor::VisitNode(const ExplodedNode *N,
  816. const ExplodedNode *PrevN,
  817. BugReporterContext &BRC,
  818. BugReport &BR) {
  819. ProgramStateRef state = N->getState();
  820. ProgramStateRef statePrev = PrevN->getState();
  821. const ObjCObjectPointerType *const *TrackedType =
  822. state->get<MostSpecializedTypeArgsMap>(Sym);
  823. const ObjCObjectPointerType *const *TrackedTypePrev =
  824. statePrev->get<MostSpecializedTypeArgsMap>(Sym);
  825. if (!TrackedType)
  826. return nullptr;
  827. if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
  828. return nullptr;
  829. // Retrieve the associated statement.
  830. const Stmt *S = PathDiagnosticLocation::getStmt(N);
  831. if (!S)
  832. return nullptr;
  833. const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
  834. SmallString<256> Buf;
  835. llvm::raw_svector_ostream OS(Buf);
  836. OS << "Type '";
  837. QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
  838. OS << "' is inferred from ";
  839. if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
  840. OS << "explicit cast (from '";
  841. QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
  842. Qualifiers(), OS, LangOpts, llvm::Twine());
  843. OS << "' to '";
  844. QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
  845. LangOpts, llvm::Twine());
  846. OS << "')";
  847. } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
  848. OS << "implicit cast (from '";
  849. QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
  850. Qualifiers(), OS, LangOpts, llvm::Twine());
  851. OS << "' to '";
  852. QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
  853. LangOpts, llvm::Twine());
  854. OS << "')";
  855. } else {
  856. OS << "this context";
  857. }
  858. // Generate the extra diagnostic.
  859. PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
  860. N->getLocationContext());
  861. return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
  862. nullptr);
  863. }
  864. /// Register checkers.
  865. void ento::registerObjCGenericsChecker(CheckerManager &mgr) {
  866. DynamicTypePropagation *checker =
  867. mgr.registerChecker<DynamicTypePropagation>();
  868. checker->CheckGenerics = true;
  869. }
  870. void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
  871. mgr.registerChecker<DynamicTypePropagation>();
  872. }