SymbolManager.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. //===- SymbolManager.h - Management of Symbolic Values --------------------===//
  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 SymbolManager, a class that manages symbolic values
  10. // created for use by ExprEngine and related classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  14. #include "clang/AST/ASTContext.h"
  15. #include "clang/AST/Expr.h"
  16. #include "clang/AST/StmtObjC.h"
  17. #include "clang/Analysis/Analyses/LiveVariables.h"
  18. #include "clang/Analysis/AnalysisDeclContext.h"
  19. #include "clang/Basic/LLVM.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  24. #include "llvm/ADT/FoldingSet.h"
  25. #include "llvm/ADT/STLExtras.h"
  26. #include "llvm/Support/Casting.h"
  27. #include "llvm/Support/Compiler.h"
  28. #include "llvm/Support/ErrorHandling.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include <cassert>
  31. using namespace clang;
  32. using namespace ento;
  33. void SymExpr::anchor() {}
  34. StringRef SymbolConjured::getKindStr() const { return "conj_$"; }
  35. StringRef SymbolDerived::getKindStr() const { return "derived_$"; }
  36. StringRef SymbolExtent::getKindStr() const { return "extent_$"; }
  37. StringRef SymbolMetadata::getKindStr() const { return "meta_$"; }
  38. StringRef SymbolRegionValue::getKindStr() const { return "reg_$"; }
  39. LLVM_DUMP_METHOD void SymExpr::dump() const { dumpToStream(llvm::errs()); }
  40. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, const SymExpr *Sym) {
  41. OS << '(';
  42. Sym->dumpToStream(OS);
  43. OS << ')';
  44. }
  45. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
  46. const llvm::APSInt &Value) {
  47. if (Value.isUnsigned())
  48. OS << Value.getZExtValue();
  49. else
  50. OS << Value.getSExtValue();
  51. if (Value.isUnsigned())
  52. OS << 'U';
  53. }
  54. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
  55. BinaryOperator::Opcode Op) {
  56. OS << ' ' << BinaryOperator::getOpcodeStr(Op) << ' ';
  57. }
  58. void SymbolCast::dumpToStream(raw_ostream &os) const {
  59. os << '(' << ToTy.getAsString() << ") (";
  60. Operand->dumpToStream(os);
  61. os << ')';
  62. }
  63. void SymbolConjured::dumpToStream(raw_ostream &os) const {
  64. os << getKindStr() << getSymbolID() << '{' << T.getAsString() << ", LC"
  65. << LCtx->getID();
  66. if (S)
  67. os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
  68. else
  69. os << ", no stmt";
  70. os << ", #" << Count << '}';
  71. }
  72. void SymbolDerived::dumpToStream(raw_ostream &os) const {
  73. os << getKindStr() << getSymbolID() << '{' << getParentSymbol() << ','
  74. << getRegion() << '}';
  75. }
  76. void SymbolExtent::dumpToStream(raw_ostream &os) const {
  77. os << getKindStr() << getSymbolID() << '{' << getRegion() << '}';
  78. }
  79. void SymbolMetadata::dumpToStream(raw_ostream &os) const {
  80. os << getKindStr() << getSymbolID() << '{' << getRegion() << ','
  81. << T.getAsString() << '}';
  82. }
  83. void SymbolData::anchor() {}
  84. void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
  85. os << getKindStr() << getSymbolID() << '<' << getType().getAsString() << ' '
  86. << R << '>';
  87. }
  88. bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
  89. return itr == X.itr;
  90. }
  91. bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
  92. return itr != X.itr;
  93. }
  94. SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
  95. itr.push_back(SE);
  96. }
  97. SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
  98. assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
  99. expand();
  100. return *this;
  101. }
  102. SymbolRef SymExpr::symbol_iterator::operator*() {
  103. assert(!itr.empty() && "attempting to dereference an 'end' iterator");
  104. return itr.back();
  105. }
  106. void SymExpr::symbol_iterator::expand() {
  107. const SymExpr *SE = itr.pop_back_val();
  108. switch (SE->getKind()) {
  109. case SymExpr::SymbolRegionValueKind:
  110. case SymExpr::SymbolConjuredKind:
  111. case SymExpr::SymbolDerivedKind:
  112. case SymExpr::SymbolExtentKind:
  113. case SymExpr::SymbolMetadataKind:
  114. return;
  115. case SymExpr::SymbolCastKind:
  116. itr.push_back(cast<SymbolCast>(SE)->getOperand());
  117. return;
  118. case SymExpr::SymIntExprKind:
  119. itr.push_back(cast<SymIntExpr>(SE)->getLHS());
  120. return;
  121. case SymExpr::IntSymExprKind:
  122. itr.push_back(cast<IntSymExpr>(SE)->getRHS());
  123. return;
  124. case SymExpr::SymSymExprKind: {
  125. const auto *x = cast<SymSymExpr>(SE);
  126. itr.push_back(x->getLHS());
  127. itr.push_back(x->getRHS());
  128. return;
  129. }
  130. }
  131. llvm_unreachable("unhandled expansion case");
  132. }
  133. const SymbolRegionValue*
  134. SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
  135. llvm::FoldingSetNodeID profile;
  136. SymbolRegionValue::Profile(profile, R);
  137. void *InsertPos;
  138. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  139. if (!SD) {
  140. SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
  141. new (SD) SymbolRegionValue(SymbolCounter, R);
  142. DataSet.InsertNode(SD, InsertPos);
  143. ++SymbolCounter;
  144. }
  145. return cast<SymbolRegionValue>(SD);
  146. }
  147. const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
  148. const LocationContext *LCtx,
  149. QualType T,
  150. unsigned Count,
  151. const void *SymbolTag) {
  152. llvm::FoldingSetNodeID profile;
  153. SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
  154. void *InsertPos;
  155. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  156. if (!SD) {
  157. SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
  158. new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
  159. DataSet.InsertNode(SD, InsertPos);
  160. ++SymbolCounter;
  161. }
  162. return cast<SymbolConjured>(SD);
  163. }
  164. const SymbolDerived*
  165. SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
  166. const TypedValueRegion *R) {
  167. llvm::FoldingSetNodeID profile;
  168. SymbolDerived::Profile(profile, parentSymbol, R);
  169. void *InsertPos;
  170. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  171. if (!SD) {
  172. SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
  173. new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
  174. DataSet.InsertNode(SD, InsertPos);
  175. ++SymbolCounter;
  176. }
  177. return cast<SymbolDerived>(SD);
  178. }
  179. const SymbolExtent*
  180. SymbolManager::getExtentSymbol(const SubRegion *R) {
  181. llvm::FoldingSetNodeID profile;
  182. SymbolExtent::Profile(profile, R);
  183. void *InsertPos;
  184. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  185. if (!SD) {
  186. SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
  187. new (SD) SymbolExtent(SymbolCounter, R);
  188. DataSet.InsertNode(SD, InsertPos);
  189. ++SymbolCounter;
  190. }
  191. return cast<SymbolExtent>(SD);
  192. }
  193. const SymbolMetadata *
  194. SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
  195. const LocationContext *LCtx,
  196. unsigned Count, const void *SymbolTag) {
  197. llvm::FoldingSetNodeID profile;
  198. SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
  199. void *InsertPos;
  200. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  201. if (!SD) {
  202. SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
  203. new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
  204. DataSet.InsertNode(SD, InsertPos);
  205. ++SymbolCounter;
  206. }
  207. return cast<SymbolMetadata>(SD);
  208. }
  209. const SymbolCast*
  210. SymbolManager::getCastSymbol(const SymExpr *Op,
  211. QualType From, QualType To) {
  212. llvm::FoldingSetNodeID ID;
  213. SymbolCast::Profile(ID, Op, From, To);
  214. void *InsertPos;
  215. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  216. if (!data) {
  217. data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
  218. new (data) SymbolCast(Op, From, To);
  219. DataSet.InsertNode(data, InsertPos);
  220. }
  221. return cast<SymbolCast>(data);
  222. }
  223. const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
  224. BinaryOperator::Opcode op,
  225. const llvm::APSInt& v,
  226. QualType t) {
  227. llvm::FoldingSetNodeID ID;
  228. SymIntExpr::Profile(ID, lhs, op, v, t);
  229. void *InsertPos;
  230. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  231. if (!data) {
  232. data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
  233. new (data) SymIntExpr(lhs, op, v, t);
  234. DataSet.InsertNode(data, InsertPos);
  235. }
  236. return cast<SymIntExpr>(data);
  237. }
  238. const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
  239. BinaryOperator::Opcode op,
  240. const SymExpr *rhs,
  241. QualType t) {
  242. llvm::FoldingSetNodeID ID;
  243. IntSymExpr::Profile(ID, lhs, op, rhs, t);
  244. void *InsertPos;
  245. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  246. if (!data) {
  247. data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
  248. new (data) IntSymExpr(lhs, op, rhs, t);
  249. DataSet.InsertNode(data, InsertPos);
  250. }
  251. return cast<IntSymExpr>(data);
  252. }
  253. const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
  254. BinaryOperator::Opcode op,
  255. const SymExpr *rhs,
  256. QualType t) {
  257. llvm::FoldingSetNodeID ID;
  258. SymSymExpr::Profile(ID, lhs, op, rhs, t);
  259. void *InsertPos;
  260. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  261. if (!data) {
  262. data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
  263. new (data) SymSymExpr(lhs, op, rhs, t);
  264. DataSet.InsertNode(data, InsertPos);
  265. }
  266. return cast<SymSymExpr>(data);
  267. }
  268. QualType SymbolConjured::getType() const {
  269. return T;
  270. }
  271. QualType SymbolDerived::getType() const {
  272. return R->getValueType();
  273. }
  274. QualType SymbolExtent::getType() const {
  275. ASTContext &Ctx = R->getMemRegionManager().getContext();
  276. return Ctx.getSizeType();
  277. }
  278. QualType SymbolMetadata::getType() const {
  279. return T;
  280. }
  281. QualType SymbolRegionValue::getType() const {
  282. return R->getValueType();
  283. }
  284. bool SymbolManager::canSymbolicate(QualType T) {
  285. T = T.getCanonicalType();
  286. if (Loc::isLocType(T))
  287. return true;
  288. if (T->isIntegralOrEnumerationType())
  289. return true;
  290. if (T->isRecordType() && !T->isUnionType())
  291. return true;
  292. return false;
  293. }
  294. void SymbolManager::addSymbolDependency(const SymbolRef Primary,
  295. const SymbolRef Dependent) {
  296. auto &dependencies = SymbolDependencies[Primary];
  297. if (!dependencies) {
  298. dependencies = std::make_unique<SymbolRefSmallVectorTy>();
  299. }
  300. dependencies->push_back(Dependent);
  301. }
  302. const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
  303. const SymbolRef Primary) {
  304. SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
  305. if (I == SymbolDependencies.end())
  306. return nullptr;
  307. return I->second.get();
  308. }
  309. void SymbolReaper::markDependentsLive(SymbolRef sym) {
  310. // Do not mark dependents more then once.
  311. SymbolMapTy::iterator LI = TheLiving.find(sym);
  312. assert(LI != TheLiving.end() && "The primary symbol is not live.");
  313. if (LI->second == HaveMarkedDependents)
  314. return;
  315. LI->second = HaveMarkedDependents;
  316. if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
  317. for (const auto I : *Deps) {
  318. if (TheLiving.find(I) != TheLiving.end())
  319. continue;
  320. markLive(I);
  321. }
  322. }
  323. }
  324. void SymbolReaper::markLive(SymbolRef sym) {
  325. TheLiving[sym] = NotProcessed;
  326. markDependentsLive(sym);
  327. }
  328. void SymbolReaper::markLive(const MemRegion *region) {
  329. RegionRoots.insert(region->getBaseRegion());
  330. markElementIndicesLive(region);
  331. }
  332. void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
  333. for (auto SR = dyn_cast<SubRegion>(region); SR;
  334. SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
  335. if (const auto ER = dyn_cast<ElementRegion>(SR)) {
  336. SVal Idx = ER->getIndex();
  337. for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
  338. markLive(*SI);
  339. }
  340. }
  341. }
  342. void SymbolReaper::markInUse(SymbolRef sym) {
  343. if (isa<SymbolMetadata>(sym))
  344. MetadataInUse.insert(sym);
  345. }
  346. bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
  347. // TODO: For now, liveness of a memory region is equivalent to liveness of its
  348. // base region. In fact we can do a bit better: say, if a particular FieldDecl
  349. // is not used later in the path, we can diagnose a leak of a value within
  350. // that field earlier than, say, the variable that contains the field dies.
  351. MR = MR->getBaseRegion();
  352. if (RegionRoots.count(MR))
  353. return true;
  354. if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
  355. return isLive(SR->getSymbol());
  356. if (const auto *VR = dyn_cast<VarRegion>(MR))
  357. return isLive(VR, true);
  358. // FIXME: This is a gross over-approximation. What we really need is a way to
  359. // tell if anything still refers to this region. Unlike SymbolicRegions,
  360. // AllocaRegions don't have associated symbols, though, so we don't actually
  361. // have a way to track their liveness.
  362. return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);
  363. }
  364. bool SymbolReaper::isLive(SymbolRef sym) {
  365. if (TheLiving.count(sym)) {
  366. markDependentsLive(sym);
  367. return true;
  368. }
  369. bool KnownLive;
  370. switch (sym->getKind()) {
  371. case SymExpr::SymbolRegionValueKind:
  372. KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
  373. break;
  374. case SymExpr::SymbolConjuredKind:
  375. KnownLive = false;
  376. break;
  377. case SymExpr::SymbolDerivedKind:
  378. KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
  379. break;
  380. case SymExpr::SymbolExtentKind:
  381. KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
  382. break;
  383. case SymExpr::SymbolMetadataKind:
  384. KnownLive = MetadataInUse.count(sym) &&
  385. isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
  386. if (KnownLive)
  387. MetadataInUse.erase(sym);
  388. break;
  389. case SymExpr::SymIntExprKind:
  390. KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
  391. break;
  392. case SymExpr::IntSymExprKind:
  393. KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
  394. break;
  395. case SymExpr::SymSymExprKind:
  396. KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
  397. isLive(cast<SymSymExpr>(sym)->getRHS());
  398. break;
  399. case SymExpr::SymbolCastKind:
  400. KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
  401. break;
  402. }
  403. if (KnownLive)
  404. markLive(sym);
  405. return KnownLive;
  406. }
  407. bool
  408. SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const {
  409. if (LCtx == nullptr)
  410. return false;
  411. if (LCtx != ELCtx) {
  412. // If the reaper's location context is a parent of the expression's
  413. // location context, then the expression value is now "out of scope".
  414. if (LCtx->isParentOf(ELCtx))
  415. return false;
  416. return true;
  417. }
  418. // If no statement is provided, everything in this and parent contexts is
  419. // live.
  420. if (!Loc)
  421. return true;
  422. return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
  423. }
  424. bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
  425. const StackFrameContext *VarContext = VR->getStackFrame();
  426. if (!VarContext)
  427. return true;
  428. if (!LCtx)
  429. return false;
  430. const StackFrameContext *CurrentContext = LCtx->getStackFrame();
  431. if (VarContext == CurrentContext) {
  432. // If no statement is provided, everything is live.
  433. if (!Loc)
  434. return true;
  435. // Anonymous parameters of an inheriting constructor are live for the entire
  436. // duration of the constructor.
  437. if (isa<CXXInheritedCtorInitExpr>(Loc))
  438. return true;
  439. if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
  440. return true;
  441. if (!includeStoreBindings)
  442. return false;
  443. unsigned &cachedQuery =
  444. const_cast<SymbolReaper *>(this)->includedRegionCache[VR];
  445. if (cachedQuery) {
  446. return cachedQuery == 1;
  447. }
  448. // Query the store to see if the region occurs in any live bindings.
  449. if (Store store = reapedStore.getStore()) {
  450. bool hasRegion =
  451. reapedStore.getStoreManager().includedInBindings(store, VR);
  452. cachedQuery = hasRegion ? 1 : 2;
  453. return hasRegion;
  454. }
  455. return false;
  456. }
  457. return VarContext->isParentOf(CurrentContext);
  458. }