DynamicTypePropagation.cpp 38 KB

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