SymbolManager.cpp 17 KB

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