Static Value-Flow Analysis
AbstractInterpretation.cpp
Go to the documentation of this file.
1 //===- AbstractExecution.cpp -- Abstract Execution---------------------------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 
24 //
25 // Created by Jiawei Wang on 2024/1/10.
26 //
27 
29 #include "AE/Svfexe/AbsExtAPI.h"
30 #include "SVFIR/SVFIR.h"
31 #include "Util/Options.h"
32 #include "Util/WorkList.h"
33 #include <cmath>
34 
35 using namespace SVF;
36 using namespace SVFUtil;
37 using namespace z3;
38 
39 
41 {
42  stat->startClk();
43  icfg = _icfg;
44  svfir = PAG::getPAG();
45  utils = new AbsExtAPI(abstractTrace);
46 
48  collectCheckPoint();
49 
50  analyse();
51  checkPointAllSet();
52  stat->endClk();
53  stat->finializeStat();
54  if (Options::PStat())
55  stat->performStat();
56  for (auto& detector: detectors)
57  detector->reportBug();
58 }
59 
61 {
62  stat = new AEStat(this);
63 }
66 {
67  delete stat;
68  for (auto it: funcToWTO)
69  delete it.second;
70 
71 }
72 
81 {
83  // Detect if the call graph has cycles by finding its strongly connected components (SCC)
84  Andersen::CallGraphSCC* callGraphScc = ander->getCallGraphSCC();
85  callGraphScc->find();
86  auto callGraph = ander->getCallGraph();
87 
88  // Iterate through the call graph
89  for (auto it = callGraph->begin(); it != callGraph->end(); it++)
90  {
91  // Check if the current function is part of a cycle
92  if (callGraphScc->isInCycle(it->second->getId()))
93  recursiveFuns.insert(it->second->getFunction()); // Mark the function as recursive
94  }
95 
96  // Initialize WTO for each function in the module
97  for (const SVFFunction* fun : svfir->getModule()->getFunctionSet())
98  {
99  if(fun->isDeclaration())
100  continue;
101  auto* wto = new ICFGWTO(icfg, icfg->getFunEntryICFGNode(fun));
102  wto->init();
103  funcToWTO[fun] = wto;
104  }
105 }
108 {
109  initWTO();
110  // handle Global ICFGNode of SVFModule
111  handleGlobalNode();
112  getAbsStateFromTrace(
113  icfg->getGlobalICFGNode())[PAG::getPAG()->getBlkPtr()] = IntervalValue::top();
114  if (const SVFFunction* fun = svfir->getModule()->getSVFFunction("main"))
115  {
116  ICFGWTO* wto = funcToWTO[fun];
117  handleWTOComponents(wto->getWTOComponents());
118  }
119 }
120 
123 {
124  const ICFGNode* node = icfg->getGlobalICFGNode();
125  abstractTrace[node] = AbstractState();
126  abstractTrace[node][SymbolTableInfo::NullPtr] = AddressValue();
127  // Global Node, we just need to handle addr, load, store, copy and gep
128  for (const SVFStmt *stmt: node->getSVFStmts())
129  {
130  handleSVFStatement(stmt);
131  }
132 }
133 
138 {
139  std::vector<AbstractState> workList;
140  AbstractState preAs;
141  for (auto& edge: icfgNode->getInEdges())
142  {
143  if (abstractTrace.find(edge->getSrcNode()) != abstractTrace.end())
144  {
145  const IntraCFGEdge *intraCfgEdge = SVFUtil::dyn_cast<IntraCFGEdge>(edge);
146  if (intraCfgEdge && intraCfgEdge->getCondition())
147  {
148  AbstractState tmpEs = abstractTrace[edge->getSrcNode()];
149  if (isBranchFeasible(intraCfgEdge, tmpEs))
150  {
151  workList.push_back(tmpEs);
152  }
153  else
154  {
155  // do nothing
156  }
157  }
158  else
159  {
160  workList.push_back(abstractTrace[edge->getSrcNode()]);
161  }
162  }
163  else
164  {
165 
166  }
167  }
168  if (workList.size() == 0)
169  {
170  return false;
171  }
172  else
173  {
174  while (!workList.empty())
175  {
176  preAs.joinWith(workList.back());
177  workList.pop_back();
178  }
179  // Has ES on the in edges - Feasible block
180  // update post as
181  abstractTrace[icfgNode] = preAs;
182  return true;
183  }
184 }
185 
186 
188  AbstractState& as)
189 {
190  AbstractState new_es = as;
191  // get cmp stmt's op0, op1, and predicate
192  NodeID op0 = cmpStmt->getOpVarID(0);
193  NodeID op1 = cmpStmt->getOpVarID(1);
194  NodeID res_id = cmpStmt->getResID();
195  s32_t predicate = cmpStmt->getPredicate();
196 
197  // if op0 or op1 is undefined, return;
198  // skip address compare
199  if (new_es.inVarToAddrsTable(op0) || new_es.inVarToAddrsTable(op1))
200  {
201  as = new_es;
202  return true;
203  }
204  const LoadStmt *load_op0 = nullptr;
205  const LoadStmt *load_op1 = nullptr;
206  // get '%1 = load i32 s', and load inst may not exist
207  SVFVar* loadVar0 = svfir->getGNode(op0);
208  if (!loadVar0->getInEdges().empty())
209  {
210  SVFStmt *loadVar0InStmt = *loadVar0->getInEdges().begin();
211  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt))
212  {
213  load_op0 = loadStmt;
214  }
215  else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar0InStmt))
216  {
217  loadVar0 = svfir->getGNode(copyStmt->getRHSVarID());
218  if (!loadVar0->getInEdges().empty())
219  {
220  SVFStmt *loadVar0InStmt2 = *loadVar0->getInEdges().begin();
221  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar0InStmt2))
222  {
223  load_op0 = loadStmt;
224  }
225  }
226  }
227  }
228 
229  SVFVar* loadVar1 = svfir->getGNode(op1);
230  if (!loadVar1->getInEdges().empty())
231  {
232  SVFStmt *loadVar1InStmt = *loadVar1->getInEdges().begin();
233  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt))
234  {
235  load_op1 = loadStmt;
236  }
237  else if (const CopyStmt *copyStmt = SVFUtil::dyn_cast<CopyStmt>(loadVar1InStmt))
238  {
239  loadVar1 = svfir->getGNode(copyStmt->getRHSVarID());
240  if (!loadVar1->getInEdges().empty())
241  {
242  SVFStmt *loadVar1InStmt2 = *loadVar1->getInEdges().begin();
243  if (const LoadStmt *loadStmt = SVFUtil::dyn_cast<LoadStmt>(loadVar1InStmt2))
244  {
245  load_op1 = loadStmt;
246  }
247  }
248  }
249  }
250  // for const X const, we may get concrete resVal instantly
251  // for var X const, we may get [0,1] if the intersection of var and const is not empty set
252  IntervalValue resVal = new_es[res_id].getInterval();
253  resVal.meet_with(IntervalValue((s64_t) succ, succ));
254  // If Var X const generates bottom value, it means this branch path is not feasible.
255  if (resVal.isBottom())
256  {
257  return false;
258  }
259 
260  bool b0 = new_es[op0].getInterval().is_numeral();
261  bool b1 = new_es[op1].getInterval().is_numeral();
262 
263  // if const X var, we should reverse op0 and op1.
264  if (b0 && !b1)
265  {
266  std::swap(op0, op1);
267  std::swap(load_op0, load_op1);
268  predicate = _switch_lhsrhs_predicate[predicate];
269  }
270  else
271  {
272  // if var X var, we cannot preset the branch condition to infer the intervals of var0,var1
273  if (!b0 && !b1)
274  {
275  as = new_es;
276  return true;
277  }
278  // if const X const, we can instantly get the resVal
279  else if (b0 && b1)
280  {
281  as = new_es;
282  return true;
283  }
284  }
285  // if cmp is 'var X const == false', we should reverse predicate 'var X' const == true'
286  // X' is reverse predicate of X
287  if (succ == 0)
288  {
289  predicate = _reverse_predicate[predicate];
290  }
291  else {}
292  // change interval range according to the compare predicate
293  AddressValue addrs;
294  if(load_op0 && new_es.inVarToAddrsTable(load_op0->getRHSVarID()))
295  addrs = new_es[load_op0->getRHSVarID()].getAddrs();
296 
297  IntervalValue &lhs = new_es[op0].getInterval(), &rhs = new_es[op1].getInterval();
298  switch (predicate)
299  {
300  case CmpStmt::Predicate::ICMP_EQ:
301  case CmpStmt::Predicate::FCMP_OEQ:
302  case CmpStmt::Predicate::FCMP_UEQ:
303  {
304  // Var == Const, so [var.lb, var.ub].meet_with(const)
305  lhs.meet_with(rhs);
306  // if lhs is register value, we should also change its mem obj
307  for (const auto &addr: addrs)
308  {
309  NodeID objId = new_es.getInternalID(addr);
310  if (new_es.inAddrToValTable(objId))
311  {
312  new_es.load(addr).meet_with(rhs);
313  }
314  }
315  break;
316  }
317  case CmpStmt::Predicate::ICMP_NE:
318  case CmpStmt::Predicate::FCMP_ONE:
319  case CmpStmt::Predicate::FCMP_UNE:
320  // Compliment set
321  break;
322  case CmpStmt::Predicate::ICMP_UGT:
323  case CmpStmt::Predicate::ICMP_SGT:
324  case CmpStmt::Predicate::FCMP_OGT:
325  case CmpStmt::Predicate::FCMP_UGT:
326  // Var > Const, so [var.lb, var.ub].meet_with([Const+1, +INF])
328  // if lhs is register value, we should also change its mem obj
329  for (const auto &addr: addrs)
330  {
331  NodeID objId = new_es.getInternalID(addr);
332  if (new_es.inAddrToValTable(objId))
333  {
334  new_es.load(addr).meet_with(
336  }
337  }
338  break;
339  case CmpStmt::Predicate::ICMP_UGE:
340  case CmpStmt::Predicate::ICMP_SGE:
341  case CmpStmt::Predicate::FCMP_OGE:
342  case CmpStmt::Predicate::FCMP_UGE:
343  {
344  // Var >= Const, so [var.lb, var.ub].meet_with([Const, +INF])
346  // if lhs is register value, we should also change its mem obj
347  for (const auto &addr: addrs)
348  {
349  NodeID objId = new_es.getInternalID(addr);
350  if (new_es.inAddrToValTable(objId))
351  {
352  new_es.load(addr).meet_with(
354  }
355  }
356  break;
357  }
358  case CmpStmt::Predicate::ICMP_ULT:
359  case CmpStmt::Predicate::ICMP_SLT:
360  case CmpStmt::Predicate::FCMP_OLT:
361  case CmpStmt::Predicate::FCMP_ULT:
362  {
363  // Var < Const, so [var.lb, var.ub].meet_with([-INF, const.ub-1])
365  // if lhs is register value, we should also change its mem obj
366  for (const auto &addr: addrs)
367  {
368  NodeID objId = new_es.getInternalID(addr);
369  if (new_es.inAddrToValTable(objId))
370  {
371  new_es.load(addr).meet_with(
373  }
374  }
375  break;
376  }
377  case CmpStmt::Predicate::ICMP_ULE:
378  case CmpStmt::Predicate::ICMP_SLE:
379  case CmpStmt::Predicate::FCMP_OLE:
380  case CmpStmt::Predicate::FCMP_ULE:
381  {
382  // Var <= Const, so [var.lb, var.ub].meet_with([-INF, const.ub])
384  // if lhs is register value, we should also change its mem obj
385  for (const auto &addr: addrs)
386  {
387  NodeID objId = new_es.getInternalID(addr);
388  if (new_es.inAddrToValTable(objId))
389  {
390  new_es.load(addr).meet_with(
392  }
393  }
394  break;
395  }
396  case CmpStmt::Predicate::FCMP_FALSE:
397  break;
398  case CmpStmt::Predicate::FCMP_TRUE:
399  break;
400  default:
401  assert(false && "implement this part");
402  abort();
403  }
404  as = new_es;
405  return true;
406 }
407 
409  AbstractState& as)
410 {
411  AbstractState new_es = as;
412  IntervalValue& switch_cond = new_es[var->getId()].getInterval();
413  s64_t value = succ;
415  for (SVFStmt *cmpVarInStmt: var->getInEdges())
416  {
417  workList.push(cmpVarInStmt);
418  }
419  switch_cond.meet_with(IntervalValue(value, value));
420  if (switch_cond.isBottom())
421  {
422  return false;
423  }
424  while(!workList.empty())
425  {
426  const SVFStmt* stmt = workList.pop();
427  if (SVFUtil::isa<CopyStmt>(stmt))
428  {
429  IntervalValue& copy_cond = new_es[var->getId()].getInterval();
430  copy_cond.meet_with(IntervalValue(value, value));
431  }
432  else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
433  {
434  if (new_es.inVarToAddrsTable(load->getRHSVarID()))
435  {
436  AddressValue &addrs = new_es[load->getRHSVarID()].getAddrs();
437  for (const auto &addr: addrs)
438  {
439  NodeID objId = new_es.getInternalID(addr);
440  if (new_es.inAddrToValTable(objId))
441  {
442  new_es.load(addr).meet_with(switch_cond);
443  }
444  }
445  }
446  }
447  }
448  as = new_es;
449  return true;
450 }
451 
453  AbstractState& as)
454 {
455  const SVFVar *cmpVar = intraEdge->getCondition();
456  if (cmpVar->getInEdges().empty())
457  {
458  return isSwitchBranchFeasible(cmpVar,
459  intraEdge->getSuccessorCondValue(), as);
460  }
461  else
462  {
463  assert(!cmpVar->getInEdges().empty() &&
464  "no in edges?");
465  SVFStmt *cmpVarInStmt = *cmpVar->getInEdges().begin();
466  if (const CmpStmt *cmpStmt = SVFUtil::dyn_cast<CmpStmt>(cmpVarInStmt))
467  {
468  return isCmpBranchFeasible(cmpStmt,
469  intraEdge->getSuccessorCondValue(), as);
470  }
471  else
472  {
473  return isSwitchBranchFeasible(
474  cmpVar, intraEdge->getSuccessorCondValue(), as);
475  }
476  }
477  return true;
478 }
481 {
482  const ICFGNode* node = icfgSingletonWto->getICFGNode();
483  stat->getBlockTrace()++;
484 
485  std::deque<const ICFGNode*> worklist;
486 
487  const std::vector<const ICFGNode*>& worklist_vec = icfg->getSubNodes(node);
488  for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
489  {
490  const ICFGNode* curNode = *it;
491  stat->getICFGNodeTrace()++;
492  // handle SVF Stmt
493  for (const SVFStmt *stmt: curNode->getSVFStmts())
494  {
495  handleSVFStatement(stmt);
496  }
497  // inlining the callee by calling handleFunc for the callee function
498  if (const CallICFGNode* callnode = SVFUtil::dyn_cast<CallICFGNode>(curNode))
499  {
500  handleCallSite(callnode);
501  }
502  for (auto& detector: detectors)
503  detector->detect(getAbsStateFromTrace(node), node);
504  stat->countStateSize();
505  }
506 }
507 
511 void AbstractInterpretation::handleWTOComponents(const std::list<const ICFGWTOComp*>& wtoComps)
512 {
513  for (const ICFGWTOComp* wtoNode : wtoComps)
514  {
515  handleWTOComponent(wtoNode);
516  }
517 }
518 
520 {
521  if (const ICFGSingletonWTO* node = SVFUtil::dyn_cast<ICFGSingletonWTO>(wtoNode))
522  {
523  if (mergeStatesFromPredecessors(node->getICFGNode()))
524  handleSingletonWTO(node);
525  }
526  // Handle WTO cycles
527  else if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(wtoNode))
528  {
529  if (mergeStatesFromPredecessors(cycle->head()->getICFGNode()))
530  handleCycleWTO(cycle);
531  }
532  // Assert false for unknown WTO types
533  else
534  {
535  assert(false && "unknown WTO type!");
536  }
537 }
538 
540 {
541  if (const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(node))
542  {
543  if (isExtCall(callNode))
544  {
545  extCallPass(callNode);
546  }
547  else if (isRecursiveCall(callNode))
548  {
549  recursiveCallPass(callNode);
550  }
551  else if (isDirectCall(callNode))
552  {
553  directCallFunPass(callNode);
554  }
555  else if (isIndirectCall(callNode))
556  {
557  indirectCallFunPass(callNode);
558  }
559  else
560  {
561  assert(false && "implement this part");
562  }
563  }
564  else
565  {
566  assert (false && "it is not call node");
567  }
568 }
569 
571 {
572  return SVFUtil::isExtCall(callNode->getCalledFunction());
573 }
574 
576 {
577  callSiteStack.push_back(callNode);
578  utils->handleExtAPI(callNode);
579  for (auto& detector : detectors)
580  {
581  detector->handleStubFunctions(callNode);
582  }
583  callSiteStack.pop_back();
584 }
585 
587 {
588  return recursiveFuns.find(callNode->getCalledFunction()) != recursiveFuns.end();
589 }
590 
592 {
593  AbstractState& as = getAbsStateFromTrace(callNode);
594  SkipRecursiveCall(callNode);
595  const RetICFGNode *retNode = callNode->getRetICFGNode();
596  if (retNode->getSVFStmts().size() > 0)
597  {
598  if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
599  {
600  if (!retPE->getLHSVar()->isPointer() &&
601  !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
602  {
603  as[retPE->getLHSVarID()] = IntervalValue::top();
604  }
605  }
606  }
607  abstractTrace[retNode] = as;
608 }
609 
611 {
612  return funcToWTO.find(callNode->getCalledFunction()) != funcToWTO.end();
613 }
615 {
616  AbstractState& as = getAbsStateFromTrace(callNode);
617  callSiteStack.push_back(callNode);
618 
619  abstractTrace[callNode] = as;
620 
621  ICFGWTO* wto = funcToWTO[callNode->getCalledFunction()];
622  handleWTOComponents(wto->getWTOComponents());
623 
624  callSiteStack.pop_back();
625  // handle Ret node
626  const RetICFGNode *retNode = callNode->getRetICFGNode();
627  // resume ES to callnode
628  abstractTrace[retNode] = abstractTrace[callNode];
629 }
630 
632 {
633  const auto callsiteMaps = svfir->getIndirectCallsites();
634  return callsiteMaps.find(callNode) != callsiteMaps.end();
635 }
636 
638 {
639  AbstractState& as = getAbsStateFromTrace(callNode);
640  const auto callsiteMaps = svfir->getIndirectCallsites();
641  NodeID call_id = callsiteMaps.at(callNode);
642  if (!as.inVarToAddrsTable(call_id))
643  {
644  return;
645  }
646  AbstractValue Addrs = as[call_id];
647  NodeID addr = *Addrs.getAddrs().begin();
648  SVFVar *func_var = svfir->getGNode(AbstractState::getInternalID(addr));
649  const SVFFunction *callfun = SVFUtil::dyn_cast<SVFFunction>(func_var->getValue());
650  if (callfun)
651  {
652  callSiteStack.push_back(callNode);
653  abstractTrace[callNode] = as;
654 
655  ICFGWTO* wto = funcToWTO[callfun];
656  handleWTOComponents(wto->getWTOComponents());
657  callSiteStack.pop_back();
658  // handle Ret node
659  const RetICFGNode *retNode = callNode->getRetICFGNode();
660  abstractTrace[retNode] = abstractTrace[callNode];
661  }
662 }
663 
664 
665 
668 {
669  const ICFGNode* cycle_head = cycle->head()->getICFGNode();
670  // Flag to indicate if we are in the increasing phase
671  bool increasing = true;
672  // Infinite loop until a fixpoint is reached,
673  for (u32_t cur_iter = 0;; cur_iter++)
674  {
675  // Start widening or narrowing if cur_iter >= widen threshold (widen delay)
676  if (cur_iter >= Options::WidenDelay())
677  {
678  // Widen or narrow after processing cycle head node
679  AbstractState prev_head_state = abstractTrace[cycle_head];
680  handleWTOComponent(cycle->head());
681  AbstractState cur_head_state = abstractTrace[cycle_head];
682  if (increasing)
683  {
684  // Widening phase
685  abstractTrace[cycle_head] = prev_head_state.widening(cur_head_state);
686  if (abstractTrace[cycle_head] == prev_head_state)
687  {
688  increasing = false;
689  continue;
690  }
691  }
692  else
693  {
694  // Widening's fixpoint reached in the widening phase, switch to narrowing
695  abstractTrace[cycle_head] = prev_head_state.narrowing(cur_head_state);
696  if (abstractTrace[cycle_head] == prev_head_state)
697  {
698  // Narrowing's fixpoint reached in the narrowing phase, exit loop
699  break;
700  }
701  }
702  }
703  else
704  {
705  // Handle the cycle head
706  handleSingletonWTO(cycle->head());
707  }
708  // Handle the cycle body
709  handleWTOComponents(cycle->getWTOComponents());
710  }
711 }
712 
714 {
715  if (const AddrStmt *addr = SVFUtil::dyn_cast<AddrStmt>(stmt))
716  {
717  updateStateOnAddr(addr);
718  }
719  else if (const BinaryOPStmt *binary = SVFUtil::dyn_cast<BinaryOPStmt>(stmt))
720  {
721  updateStateOnBinary(binary);
722  }
723  else if (const CmpStmt *cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
724  {
725  updateStateOnCmp(cmp);
726  }
727  else if (SVFUtil::isa<UnaryOPStmt>(stmt))
728  {
729  }
730  else if (SVFUtil::isa<BranchStmt>(stmt))
731  {
732  // branch stmt is handled in hasBranchES
733  }
734  else if (const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(stmt))
735  {
736  updateStateOnLoad(load);
737  }
738  else if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
739  {
740  updateStateOnStore(store);
741  }
742  else if (const CopyStmt *copy = SVFUtil::dyn_cast<CopyStmt>(stmt))
743  {
744  updateStateOnCopy(copy);
745  }
746  else if (const GepStmt *gep = SVFUtil::dyn_cast<GepStmt>(stmt))
747  {
748  updateStateOnGep(gep);
749  }
750  else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt))
751  {
752  updateStateOnSelect(select);
753  }
754  else if (const PhiStmt *phi = SVFUtil::dyn_cast<PhiStmt>(stmt))
755  {
756  updateStateOnPhi(phi);
757  }
758  else if (const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
759  {
760  // To handle Call Edge
761  updateStateOnCall(callPE);
762  }
763  else if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
764  {
765  updateStateOnRet(retPE);
766  }
767  else
768  assert(false && "implement this part");
769 }
770 
771 
773 {
774  AbstractState& as = getAbsStateFromTrace(callNode);
775  const RetICFGNode *retNode = callNode->getRetICFGNode();
776  if (retNode->getSVFStmts().size() > 0)
777  {
778  if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(*retNode->getSVFStmts().begin()))
779  {
780  AbstractState as;
781  if (!retPE->getLHSVar()->isPointer() && !retPE->getLHSVar()->isConstDataOrAggDataButNotNullPtr())
782  as[retPE->getLHSVarID()] = IntervalValue::top();
783  }
784  }
785  if (!retNode->getOutEdges().empty())
786  {
787  if (retNode->getOutEdges().size() == 1)
788  {
789 
790  }
791  else
792  {
793  return;
794  }
795  }
797  FIFOWorkList<const ICFGNode *> instWorklist;
798  for (const SVFBasicBlock * bb: callNode->getCalledFunction()->getReachableBBs())
799  {
800  for (const ICFGNode* node: bb->getICFGNodeList())
801  {
802  for (const SVFStmt *stmt: node->getSVFStmts())
803  {
804  if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt))
805  {
806  const SVFVar *rhsVar = store->getRHSVar();
807  u32_t lhs = store->getLHSVarID();
808  if (as.inVarToAddrsTable(lhs))
809  {
810  if (!rhsVar->isPointer() && !rhsVar->isConstDataOrAggDataButNotNullPtr())
811  {
812  const AbstractValue &addrs = as[lhs];
813  for (const auto &addr: addrs.getAddrs())
814  {
815  as.store(addr, IntervalValue::top());
816  }
817  }
818  }
819  }
820  }
821  }
822  }
823 }
824 
825 // count the size of memory map
827 {
828  if (count == 0)
829  {
830  generalNumMap["ES_Var_AVG_Num"] = 0;
831  generalNumMap["ES_Loc_AVG_Num"] = 0;
832  generalNumMap["ES_Var_Addr_AVG_Num"] = 0;
833  generalNumMap["ES_Loc_Addr_AVG_Num"] = 0;
834  }
835  ++count;
836 }
837 
839 {
840  memUsage = getMemUsage();
841  if (count > 0)
842  {
843  generalNumMap["ES_Var_AVG_Num"] /= count;
844  generalNumMap["ES_Loc_AVG_Num"] /= count;
845  generalNumMap["ES_Var_Addr_AVG_Num"] /= count;
846  generalNumMap["ES_Loc_Addr_AVG_Num"] /= count;
847  }
848  generalNumMap["SVF_STMT_NUM"] = count;
849  generalNumMap["ICFG_Node_Num"] = _ae->svfir->getICFG()->nodeNum;
850  u32_t callSiteNum = 0;
851  u32_t extCallSiteNum = 0;
853  for (const auto &it: *_ae->svfir->getICFG())
854  {
855  if (it.second->getFun())
856  {
857  funs.insert(it.second->getFun());
858  }
859  if (const CallICFGNode *callNode = dyn_cast<CallICFGNode>(it.second))
860  {
861  if (!isExtCall(callNode))
862  {
863  callSiteNum++;
864  }
865  else
866  {
867  extCallSiteNum++;
868  }
869  }
870  }
871  generalNumMap["Func_Num"] = funs.size();
872  generalNumMap["EXT_CallSite_Num"] = extCallSiteNum;
873  generalNumMap["NonEXT_CallSite_Num"] = callSiteNum;
874  timeStatMap["Total_Time(sec)"] = (double)(endTime - startTime) / TIMEINTERVAL;
875 
876 }
877 
879 {
880  std::string fullName(_ae->moduleName);
882  std::string moduleName;
883  if (fullName.find('/') == std::string::npos)
884  {
885  std::string name = fullName;
886  moduleName = name.substr(0, fullName.find('.'));
887  }
888  else
889  {
890  std::string name = fullName.substr(fullName.find('/'), fullName.size());
891  moduleName = name.substr(0, fullName.find('.'));
892  }
893 
894  SVFUtil::outs() << "\n************************\n";
895  SVFUtil::outs() << "################ (program : " << moduleName << ")###############\n";
896  SVFUtil::outs().flags(std::ios::left);
897  unsigned field_width = 30;
898  for (NUMStatMap::iterator it = generalNumMap.begin(), eit = generalNumMap.end(); it != eit; ++it)
899  {
900  // format out put with width 20 space
901  std::cout << std::setw(field_width) << it->first << it->second << "\n";
902  }
903  SVFUtil::outs() << "-------------------------------------------------------\n";
904  for (TIMEStatMap::iterator it = timeStatMap.begin(), eit = timeStatMap.end(); it != eit; ++it)
905  {
906  // format out put with width 20 space
907  SVFUtil::outs() << std::setw(field_width) << it->first << it->second << "\n";
908  }
909  SVFUtil::outs() << "Memory usage: " << memUsage << "\n";
910 
911  SVFUtil::outs() << "#######################################################" << std::endl;
912  SVFUtil::outs().flush();
913 }
914 
916 {
917  // traverse every ICFGNode
918  Set<std::string> ae_checkpoint_names = {"svf_assert"};
919  Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
920 
921  for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
922  {
923  const ICFGNode* node = it->second;
924  if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
925  {
926  if (const SVFFunction *fun = call->getCalledFunction())
927  {
928  if (ae_checkpoint_names.find(fun->getName()) !=
929  ae_checkpoint_names.end())
930  {
931  checkpoints.insert(call);
932  }
934  {
935  if (buf_checkpoint_names.find(fun->getName()) !=
936  buf_checkpoint_names.end())
937  {
938  checkpoints.insert(call);
939  }
940  }
941  }
942  }
943  }
944 }
945 
947 {
948  if (checkpoints.size() == 0)
949  {
950  return;
951  }
952  else
953  {
954  SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
955  for (const CallICFGNode* call: checkpoints)
956  SVFUtil::errs() << call->toString() + "\n";
957  assert(false);
958  }
959 
960 }
961 
963 {
964  AbstractState& as = getAbsStateFromTrace(gep->getICFGNode());
965  u32_t rhs = gep->getRHSVarID();
966  u32_t lhs = gep->getLHSVarID();
967  IntervalValue offsetPair = as.getElementIndex(gep);
968  AbstractValue gepAddrs;
969  APOffset lb = offsetPair.lb().getIntNumeral() < Options::MaxFieldLimit()?
970  offsetPair.lb().getIntNumeral(): Options::MaxFieldLimit();
971  APOffset ub = offsetPair.ub().getIntNumeral() < Options::MaxFieldLimit()?
972  offsetPair.ub().getIntNumeral(): Options::MaxFieldLimit();
973  for (APOffset i = lb; i <= ub; i++)
974  gepAddrs.join_with(as.getGepObjAddrs(rhs,IntervalValue(i)));
975  as[lhs] = gepAddrs;
976 }
977 
979 {
980  AbstractState& as = getAbsStateFromTrace(select->getICFGNode());
981  u32_t res = select->getResID();
982  u32_t tval = select->getTrueValue()->getId();
983  u32_t fval = select->getFalseValue()->getId();
984  u32_t cond = select->getCondition()->getId();
985  if (as[cond].getInterval().is_numeral())
986  {
987  as[res] = as[cond].getInterval().is_zero() ? as[fval] : as[tval];
988  }
989  else
990  {
991  as[res] = as[tval];
992  as[res].join_with(as[fval]);
993  }
994 }
995 
997 {
998  const ICFGNode* icfgNode = phi->getICFGNode();
999  AbstractState& as = getAbsStateFromTrace(icfgNode);
1000  u32_t res = phi->getResID();
1001  AbstractValue rhs;
1002  for (u32_t i = 0; i < phi->getOpVarNum(); i++)
1003  {
1004  NodeID curId = phi->getOpVarID(i);
1005  const ICFGNode* opICFGNode = phi->getOpICFGNode(i);
1006  if (hasAbsStateFromTrace(opICFGNode))
1007  {
1008  AbstractState tmpEs = abstractTrace[opICFGNode];
1009  AbstractState& opAs = getAbsStateFromTrace(opICFGNode);
1010  const ICFGEdge* edge = icfg->getICFGEdge(opICFGNode, icfgNode, ICFGEdge::IntraCF);
1011  // if IntraEdge, check the condition, if it is feasible, join the value
1012  // if IntraEdge but not conditional edge, join the value
1013  // if not IntraEdge, join the value
1014  if (edge)
1015  {
1016  const IntraCFGEdge* intraEdge = SVFUtil::cast<IntraCFGEdge>(edge);
1017  if (intraEdge->getCondition())
1018  {
1019  if (isBranchFeasible(intraEdge, tmpEs))
1020  rhs.join_with(opAs[curId]);
1021  }
1022  else
1023  rhs.join_with(opAs[curId]);
1024  }
1025  else
1026  {
1027  rhs.join_with(opAs[curId]);
1028  }
1029  }
1030  }
1031  as[res] = rhs;
1032 }
1033 
1034 
1036 {
1037  AbstractState& as = getAbsStateFromTrace(callPE->getICFGNode());
1038  NodeID lhs = callPE->getLHSVarID();
1039  NodeID rhs = callPE->getRHSVarID();
1040  as[lhs] = as[rhs];
1041 }
1042 
1044 {
1045  AbstractState& as = getAbsStateFromTrace(retPE->getICFGNode());
1046  NodeID lhs = retPE->getLHSVarID();
1047  NodeID rhs = retPE->getRHSVarID();
1048  as[lhs] = as[rhs];
1049 }
1050 
1051 
1053 {
1054  AbstractState& as = getAbsStateFromTrace(addr->getICFGNode());
1055  as.initObjVar(SVFUtil::cast<ObjVar>(addr->getRHSVar()));
1056  if (addr->getRHSVar()->getType()->getKind() == SVFType::SVFIntegerTy)
1057  as[addr->getRHSVarID()].getInterval().meet_with(utils->getRangeLimitFromType(addr->getRHSVar()->getType()));
1058  as[addr->getLHSVarID()] = as[addr->getRHSVarID()];
1059 }
1060 
1061 
1063 {
1067  const ICFGNode* node = binary->getICFGNode();
1068  AbstractState& as = getAbsStateFromTrace(node);
1069  u32_t op0 = binary->getOpVarID(0);
1070  u32_t op1 = binary->getOpVarID(1);
1071  u32_t res = binary->getResID();
1072  if (!as.inVarToValTable(op0)) as[op0] = IntervalValue::top();
1073  if (!as.inVarToValTable(op1)) as[op1] = IntervalValue::top();
1074  IntervalValue &lhs = as[op0].getInterval(), &rhs = as[op1].getInterval();
1075  IntervalValue resVal;
1076  switch (binary->getOpcode())
1077  {
1078  case BinaryOPStmt::Add:
1079  case BinaryOPStmt::FAdd:
1080  resVal = (lhs + rhs);
1081  break;
1082  case BinaryOPStmt::Sub:
1083  case BinaryOPStmt::FSub:
1084  resVal = (lhs - rhs);
1085  break;
1086  case BinaryOPStmt::Mul:
1087  case BinaryOPStmt::FMul:
1088  resVal = (lhs * rhs);
1089  break;
1090  case BinaryOPStmt::SDiv:
1091  case BinaryOPStmt::FDiv:
1092  case BinaryOPStmt::UDiv:
1093  resVal = (lhs / rhs);
1094  break;
1095  case BinaryOPStmt::SRem:
1096  case BinaryOPStmt::FRem:
1097  case BinaryOPStmt::URem:
1098  resVal = (lhs % rhs);
1099  break;
1100  case BinaryOPStmt::Xor:
1101  resVal = (lhs ^ rhs);
1102  break;
1103  case BinaryOPStmt::And:
1104  resVal = (lhs & rhs);
1105  break;
1106  case BinaryOPStmt::Or:
1107  resVal = (lhs | rhs);
1108  break;
1109  case BinaryOPStmt::AShr:
1110  resVal = (lhs >> rhs);
1111  break;
1112  case BinaryOPStmt::Shl:
1113  resVal = (lhs << rhs);
1114  break;
1115  case BinaryOPStmt::LShr:
1116  resVal = (lhs >> rhs);
1117  break;
1118  default:
1119  assert(false && "undefined binary: ");
1120  }
1121  as[res] = resVal;
1122 }
1123 
1125 {
1126  AbstractState& as = getAbsStateFromTrace(cmp->getICFGNode());
1127  u32_t op0 = cmp->getOpVarID(0);
1128  u32_t op1 = cmp->getOpVarID(1);
1129  // if it is address
1130  if (as.inVarToAddrsTable(op0) && as.inVarToAddrsTable(op1))
1131  {
1132  IntervalValue resVal;
1133  AddressValue addrOp0 = as[op0].getAddrs();
1134  AddressValue addrOp1 = as[op1].getAddrs();
1135  u32_t res = cmp->getResID();
1136  if (addrOp0.equals(addrOp1))
1137  {
1138  resVal = IntervalValue(1, 1);
1139  }
1140  else if (addrOp0.hasIntersect(addrOp1))
1141  {
1142  resVal = IntervalValue(0, 1);
1143  }
1144  else
1145  {
1146  resVal = IntervalValue(0, 0);
1147  }
1148  as[res] = resVal;
1149  }
1150  else
1151  {
1152  if (!as.inVarToValTable(op0))
1153  as[op0] = IntervalValue::top();
1154  if (!as.inVarToValTable(op1))
1155  as[op1] = IntervalValue::top();
1156  u32_t res = cmp->getResID();
1157  if (as.inVarToValTable(op0) && as.inVarToValTable(op1))
1158  {
1159  IntervalValue resVal;
1160  if (as[op0].isInterval() && as[op1].isInterval())
1161  {
1162  IntervalValue &lhs = as[op0].getInterval(),
1163  &rhs = as[op1].getInterval();
1164  // AbstractValue
1165  auto predicate = cmp->getPredicate();
1166  switch (predicate)
1167  {
1168  case CmpStmt::ICMP_EQ:
1169  case CmpStmt::FCMP_OEQ:
1170  case CmpStmt::FCMP_UEQ:
1171  resVal = (lhs == rhs);
1172  // resVal = (lhs.getInterval() == rhs.getInterval());
1173  break;
1174  case CmpStmt::ICMP_NE:
1175  case CmpStmt::FCMP_ONE:
1176  case CmpStmt::FCMP_UNE:
1177  resVal = (lhs != rhs);
1178  break;
1179  case CmpStmt::ICMP_UGT:
1180  case CmpStmt::ICMP_SGT:
1181  case CmpStmt::FCMP_OGT:
1182  case CmpStmt::FCMP_UGT:
1183  resVal = (lhs > rhs);
1184  break;
1185  case CmpStmt::ICMP_UGE:
1186  case CmpStmt::ICMP_SGE:
1187  case CmpStmt::FCMP_OGE:
1188  case CmpStmt::FCMP_UGE:
1189  resVal = (lhs >= rhs);
1190  break;
1191  case CmpStmt::ICMP_ULT:
1192  case CmpStmt::ICMP_SLT:
1193  case CmpStmt::FCMP_OLT:
1194  case CmpStmt::FCMP_ULT:
1195  resVal = (lhs < rhs);
1196  break;
1197  case CmpStmt::ICMP_ULE:
1198  case CmpStmt::ICMP_SLE:
1199  case CmpStmt::FCMP_OLE:
1200  case CmpStmt::FCMP_ULE:
1201  resVal = (lhs <= rhs);
1202  break;
1203  case CmpStmt::FCMP_FALSE:
1204  resVal = IntervalValue(0, 0);
1205  break;
1206  case CmpStmt::FCMP_TRUE:
1207  resVal = IntervalValue(1, 1);
1208  break;
1209  default:
1210  {
1211  assert(false && "undefined compare: ");
1212  }
1213  }
1214  as[res] = resVal;
1215  }
1216  else if (as[op0].isAddr() && as[op1].isAddr())
1217  {
1218  AddressValue &lhs = as[op0].getAddrs(),
1219  &rhs = as[op1].getAddrs();
1220  auto predicate = cmp->getPredicate();
1221  switch (predicate)
1222  {
1223  case CmpStmt::ICMP_EQ:
1224  case CmpStmt::FCMP_OEQ:
1225  case CmpStmt::FCMP_UEQ:
1226  {
1227  if (lhs.hasIntersect(rhs))
1228  {
1229  resVal = IntervalValue(0, 1);
1230  }
1231  else if (lhs.empty() && rhs.empty())
1232  {
1233  resVal = IntervalValue(1, 1);
1234  }
1235  else
1236  {
1237  resVal = IntervalValue(0, 0);
1238  }
1239  break;
1240  }
1241  case CmpStmt::ICMP_NE:
1242  case CmpStmt::FCMP_ONE:
1243  case CmpStmt::FCMP_UNE:
1244  {
1245  if (lhs.hasIntersect(rhs))
1246  {
1247  resVal = IntervalValue(0, 1);
1248  }
1249  else if (lhs.empty() && rhs.empty())
1250  {
1251  resVal = IntervalValue(0, 0);
1252  }
1253  else
1254  {
1255  resVal = IntervalValue(1, 1);
1256  }
1257  break;
1258  }
1259  case CmpStmt::ICMP_UGT:
1260  case CmpStmt::ICMP_SGT:
1261  case CmpStmt::FCMP_OGT:
1262  case CmpStmt::FCMP_UGT:
1263  {
1264  if (lhs.size() == 1 && rhs.size() == 1)
1265  {
1266  resVal = IntervalValue(*lhs.begin() > *rhs.begin());
1267  }
1268  else
1269  {
1270  resVal = IntervalValue(0, 1);
1271  }
1272  break;
1273  }
1274  case CmpStmt::ICMP_UGE:
1275  case CmpStmt::ICMP_SGE:
1276  case CmpStmt::FCMP_OGE:
1277  case CmpStmt::FCMP_UGE:
1278  {
1279  if (lhs.size() == 1 && rhs.size() == 1)
1280  {
1281  resVal = IntervalValue(*lhs.begin() >= *rhs.begin());
1282  }
1283  else
1284  {
1285  resVal = IntervalValue(0, 1);
1286  }
1287  break;
1288  }
1289  case CmpStmt::ICMP_ULT:
1290  case CmpStmt::ICMP_SLT:
1291  case CmpStmt::FCMP_OLT:
1292  case CmpStmt::FCMP_ULT:
1293  {
1294  if (lhs.size() == 1 && rhs.size() == 1)
1295  {
1296  resVal = IntervalValue(*lhs.begin() < *rhs.begin());
1297  }
1298  else
1299  {
1300  resVal = IntervalValue(0, 1);
1301  }
1302  break;
1303  }
1304  case CmpStmt::ICMP_ULE:
1305  case CmpStmt::ICMP_SLE:
1306  case CmpStmt::FCMP_OLE:
1307  case CmpStmt::FCMP_ULE:
1308  {
1309  if (lhs.size() == 1 && rhs.size() == 1)
1310  {
1311  resVal = IntervalValue(*lhs.begin() <= *rhs.begin());
1312  }
1313  else
1314  {
1315  resVal = IntervalValue(0, 1);
1316  }
1317  break;
1318  }
1319  case CmpStmt::FCMP_FALSE:
1320  resVal = IntervalValue(0, 0);
1321  break;
1322  case CmpStmt::FCMP_TRUE:
1323  resVal = IntervalValue(1, 1);
1324  break;
1325  default:
1326  {
1327  assert(false && "undefined compare: ");
1328  }
1329  }
1330  as[res] = resVal;
1331  }
1332  }
1333  }
1334 }
1335 
1337 {
1338  AbstractState& as = getAbsStateFromTrace(load->getICFGNode());
1339  u32_t rhs = load->getRHSVarID();
1340  u32_t lhs = load->getLHSVarID();
1341  as[lhs] = as.loadValue(rhs);
1342 }
1343 
1345 {
1346  AbstractState& as = getAbsStateFromTrace(store->getICFGNode());
1347  u32_t rhs = store->getRHSVarID();
1348  u32_t lhs = store->getLHSVarID();
1349  as.storeValue(lhs, as[rhs]);
1350 }
1351 
1353 {
1354  auto getZExtValue = [](AbstractState& as, const SVFVar* var)
1355  {
1356  const SVFType* type = var->getType();
1357  if (SVFUtil::isa<SVFIntegerType>(type))
1358  {
1359  u32_t bits = type->getByteSize() * 8;
1360  if (as[var->getId()].getInterval().is_numeral())
1361  {
1362  if (bits == 8)
1363  {
1364  int8_t signed_i8_value = as[var->getId()].getInterval().getIntNumeral();
1365  u32_t unsigned_value = static_cast<uint8_t>(signed_i8_value);
1366  return IntervalValue(unsigned_value, unsigned_value);
1367  }
1368  else if (bits == 16)
1369  {
1370  s16_t signed_i16_value = as[var->getId()].getInterval().getIntNumeral();
1371  u32_t unsigned_value = static_cast<u16_t>(signed_i16_value);
1372  return IntervalValue(unsigned_value, unsigned_value);
1373  }
1374  else if (bits == 32)
1375  {
1376  s32_t signed_i32_value = as[var->getId()].getInterval().getIntNumeral();
1377  u32_t unsigned_value = static_cast<u32_t>(signed_i32_value);
1378  return IntervalValue(unsigned_value, unsigned_value);
1379  }
1380  else if (bits == 64)
1381  {
1382  s64_t signed_i64_value = as[var->getId()].getInterval().getIntNumeral();
1383  return IntervalValue((s64_t)signed_i64_value, (s64_t)signed_i64_value);
1384  // we only support i64 at most
1385  }
1386  else
1387  {
1388  assert(false && "cannot support int type other than u8/16/32/64");
1389  }
1390  }
1391  else
1392  {
1393  return IntervalValue::top(); // TODO: may have better solution
1394  }
1395  }
1396  return IntervalValue::top(); // TODO: may have better solution
1397  };
1398 
1399  auto getTruncValue = [&](const AbstractState& as, const SVF::SVFVar* var,
1400  const SVFType* dstType)
1401  {
1402  const IntervalValue& itv = as[var->getId()].getInterval();
1403  if(itv.isBottom()) return itv;
1404  // get the value of ub and lb
1405  s64_t int_lb = itv.lb().getIntNumeral();
1406  s64_t int_ub = itv.ub().getIntNumeral();
1407  // get dst type
1408  u32_t dst_bits = dstType->getByteSize() * 8;
1409  if (dst_bits == 8)
1410  {
1411  // get the signed value of ub and lb
1412  int8_t s8_lb = static_cast<int8_t>(int_lb);
1413  int8_t s8_ub = static_cast<int8_t>(int_ub);
1414  if (s8_lb > s8_ub)
1415  {
1416  // return range of s8
1417  return utils->getRangeLimitFromType(dstType);
1418  }
1419  return IntervalValue(s8_lb, s8_ub);
1420  }
1421  else if (dst_bits == 16)
1422  {
1423  // get the signed value of ub and lb
1424  s16_t s16_lb = static_cast<s16_t>(int_lb);
1425  s16_t s16_ub = static_cast<s16_t>(int_ub);
1426  if (s16_lb > s16_ub)
1427  {
1428  // return range of s16
1429  return utils->getRangeLimitFromType(dstType);
1430  }
1431  return IntervalValue(s16_lb, s16_ub);
1432  }
1433  else if (dst_bits == 32)
1434  {
1435  // get the signed value of ub and lb
1436  s32_t s32_lb = static_cast<s32_t>(int_lb);
1437  s32_t s32_ub = static_cast<s32_t>(int_ub);
1438  if (s32_lb > s32_ub)
1439  {
1440  // return range of s32
1441  return utils->getRangeLimitFromType(dstType);
1442  }
1443  return IntervalValue(s32_lb, s32_ub);
1444  }
1445  else
1446  {
1447  assert(false && "cannot support dst int type other than u8/16/32");
1448  }
1449  };
1450 
1451  AbstractState& as = getAbsStateFromTrace(copy->getICFGNode());
1452  u32_t lhs = copy->getLHSVarID();
1453  u32_t rhs = copy->getRHSVarID();
1454 
1455  if (copy->getCopyKind() == CopyStmt::COPYVAL)
1456  {
1457  as[lhs] = as[rhs];
1458  }
1459  else if (copy->getCopyKind() == CopyStmt::ZEXT)
1460  {
1461  as[lhs] = getZExtValue(as, copy->getRHSVar());
1462  }
1463  else if (copy->getCopyKind() == CopyStmt::SEXT)
1464  {
1465  as[lhs] = as[rhs].getInterval();
1466  }
1467  else if (copy->getCopyKind() == CopyStmt::FPTOSI)
1468  {
1469  as[lhs] = as[rhs].getInterval();
1470  }
1471  else if (copy->getCopyKind() == CopyStmt::FPTOUI)
1472  {
1473  as[lhs] = as[rhs].getInterval();
1474  }
1475  else if (copy->getCopyKind() == CopyStmt::SITOFP)
1476  {
1477  as[lhs] = as[rhs].getInterval();
1478  }
1479  else if (copy->getCopyKind() == CopyStmt::UITOFP)
1480  {
1481  as[lhs] = as[rhs].getInterval();
1482  }
1483  else if (copy->getCopyKind() == CopyStmt::TRUNC)
1484  {
1485  as[lhs] = getTruncValue(as, copy->getRHSVar(), copy->getLHSVar()->getType());
1486  }
1487  else if (copy->getCopyKind() == CopyStmt::FPTRUNC)
1488  {
1489  as[lhs] = as[rhs].getInterval();
1490  }
1491  else if (copy->getCopyKind() == CopyStmt::INTTOPTR)
1492  {
1493  //insert nullptr
1494  }
1495  else if (copy->getCopyKind() == CopyStmt::PTRTOINT)
1496  {
1497  as[lhs] = IntervalValue::top();
1498  }
1499  else if (copy->getCopyKind() == CopyStmt::BITCAST)
1500  {
1501  if (as[rhs].isAddr())
1502  {
1503  as[lhs] = as[rhs];
1504  }
1505  else
1506  {
1507  // do nothing
1508  }
1509  }
1510  else
1511  {
1512  assert(false && "undefined copy kind");
1513  abort();
1514  }
1515 }
1516 
1517 
1518 
#define TIMEINTERVAL
Definition: SVFType.h:512
newitem type
Definition: cJSON.cpp:2739
copy
Definition: cJSON.cpp:414
const char *const name
Definition: cJSON.h:264
int count
Definition: cJSON.h:216
const char *const string
Definition: cJSON.h:172
AEStat: Statistic for AE.
void performStat() override
Handles external API calls and manages abstract states.
Definition: AbsExtAPI.h:46
void updateStateOnCall(const CallPE *callPE)
virtual bool isRecursiveCall(const CallICFGNode *callNode)
virtual void recursiveCallPass(const CallICFGNode *callNode)
void updateStateOnStore(const StoreStmt *store)
virtual bool isDirectCall(const CallICFGNode *callNode)
virtual void handleCycleWTO(const ICFGCycleWTO *cycle)
handle wto cycle (loop)
void updateStateOnGep(const GepStmt *gep)
virtual void extCallPass(const CallICFGNode *callNode)
virtual void handleGlobalNode()
Global ICFGNode is handled at the entry of the program,.
bool mergeStatesFromPredecessors(const ICFGNode *icfgNode)
virtual void directCallFunPass(const CallICFGNode *callNode)
void handleWTOComponent(const ICFGWTOComp *wtoComp)
virtual bool isExtCall(const CallICFGNode *callNode)
virtual bool isIndirectCall(const CallICFGNode *callNode)
void initWTO()
Mark recursive functions in the call graph.
void updateStateOnPhi(const PhiStmt *phi)
bool isBranchFeasible(const IntraCFGEdge *intraEdge, AbstractState &as)
bool isSwitchBranchFeasible(const SVFVar *var, s64_t succ, AbstractState &as)
void updateStateOnSelect(const SelectStmt *select)
virtual void handleSVFStatement(const SVFStmt *stmt)
virtual void indirectCallFunPass(const CallICFGNode *callNode)
virtual void runOnModule(ICFG *icfg)
void updateStateOnAddr(const AddrStmt *addr)
virtual ~AbstractInterpretation()
Destructor.
bool isCmpBranchFeasible(const CmpStmt *cmpStmt, s64_t succ, AbstractState &as)
virtual void handleCallSite(const ICFGNode *node)
void updateStateOnRet(const RetPE *retPE)
void handleWTOComponents(const std::list< const ICFGWTOComp * > &wtoComps)
Hanlde two types of WTO components (singleton and cycle)
void updateStateOnCopy(const CopyStmt *copy)
void updateStateOnLoad(const LoadStmt *load)
void updateStateOnBinary(const BinaryOPStmt *binary)
virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto)
handle instructions in svf basic blocks
void updateStateOnCmp(const CmpStmt *cmp)
virtual void SkipRecursiveCall(const CallICFGNode *callnode)
void store(u32_t addr, const AbstractValue &val)
virtual bool inAddrToValTable(u32_t id) const
whether the memory address stores abstract value
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
IntervalValue getElementIndex(const GepStmt *gep)
virtual AbstractValue & load(u32_t addr)
AbstractValue loadValue(NodeID varId)
bool inVarToAddrsTable(u32_t id) const
whether the variable is in varToAddrs table
AbstractState narrowing(const AbstractState &other)
domain narrow with other, and return the narrowed domain
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
virtual bool inVarToValTable(u32_t id) const
whether the variable is in varToVal table
void storeValue(NodeID varId, AbstractValue val)
AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset)
void initObjVar(ObjVar *objVar)
AbstractState widening(const AbstractState &other)
domain widen with other, and return the widened domain
void meet_with(const AbstractValue &other)
void join_with(const AbstractValue &other)
AddressValue & getAddrs()
bool equals(const AddressValue &rhs) const
Definition: AddressValue.h:87
bool hasIntersect(const AddressValue &other)
Definition: AddressValue.h:164
bool empty() const
Definition: AddressValue.h:102
u32_t size() const
Definition: AddressValue.h:107
AddrSet::const_iterator begin() const
Definition: AddressValue.h:92
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:408
NodeID getRHSVarID() const
NodeID getLHSVarID() const
SVFVar * getRHSVar() const
u32_t getOpcode() const
s64_t getIntNumeral() const
Definition: NumericValue.h:703
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition: ICFGNode.h:457
u32_t getPredicate() const
@ ICMP_SGT
signed greater than
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ ICMP_UGE
unsigned greater or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ ICMP_ULE
unsigned less or equal
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_NE
not equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_ULT
unsigned less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ ICMP_SLT
signed less than
@ ICMP_UGT
unsigned greater than
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_SLE
signed less or equal
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
const SVFStmtList & getSVFStmts() const
Definition: ICFGNode.h:117
Definition: ICFG.h:48
NodeID getBlkPtr() const
Definition: IRGraph.h:169
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
static BoundedInt minus_infinity()
Get minus infinity -inf.
Definition: IntervalValue.h:77
const BoundedInt & lb() const
Return the lower bound.
bool isBottom() const
Definition: IntervalValue.h:71
const BoundedInt & ub() const
Return the upper bound.
static BoundedInt plus_infinity()
Get plus infinity +inf.
Definition: IntervalValue.h:83
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
Definition: IntervalValue.h:94
s64_t getSuccessorCondValue() const
Definition: ICFGEdge.h:147
const SVFVar * getCondition() const
Definition: ICFGEdge.h:142
NodeID getOpVarID(u32_t pos) const
NodeID getResID() const
u32_t getOpVarNum() const
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition: Options.h:38
static const Option< u32_t > WidenDelay
Definition: Options.h:246
static const Option< bool > PStat
Definition: Options.h:119
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition: Options.h:252
const ICFGNode * getOpICFGNode(u32_t op_idx) const
Return the corresponding ICFGNode of this operand.
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
PTACallGraph * getCallGraph() const
Return call graph.
void find(void)
Definition: SCC.h:308
bool isInCycle(NodeID n) const
whether the node is in a cycle
Definition: SCC.h:149
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const std::vector< const SVFBasicBlock * > & getReachableBBs() const
Definition: SVFValue.h:450
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
ICFGNode * getICFGNode() const
@ SVFIntegerTy
Definition: SVFType.h:169
GNodeK getKind() const
Definition: SVFType.h:213
bool isConstDataOrAggDataButNotNullPtr() const
virtual bool isPointer() const
Whether it is a pointer.
Definition: SVFVariables.h:106
virtual const SVFType * getType() const
Return type of the value.
Definition: SVFVariables.h:96
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
const SVFVar * getTrueValue() const
const SVFVar * getCondition() const
const SVFVar * getFalseValue() const
const WTONode< GraphT > * head() const
Return the head of the cycle.
Definition: WTO.h:412
const WTOComponentRefList & getWTOComponents() const
Get all wto components in WTO cycle.
Definition: WTO.h:418
const NodeT * getICFGNode() const
Return the graph node.
Definition: WTO.h:344
const WTOComponentRefList & getWTOComponents() const
Get all wto components in WTO.
Definition: WTO.h:589
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
std::ostream & errs()
Overwrite llvm::errs()
Definition: SVFUtil.h:56
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55
s64_t APOffset
Definition: GeneralType.h:60
signed short s16_t
Definition: GeneralType.h:53
unsigned short u16_t
Definition: GeneralType.h:52
signed s32_t
Definition: GeneralType.h:47
unsigned u32_t
Definition: GeneralType.h:46
signed long long s64_t
Definition: GeneralType.h:49
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96