Static Value-Flow Analysis
ProgSlice.cpp
Go to the documentation of this file.
1 //===- ProgSlice.cpp -- Program slicing--------------------------------------//
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  * ProgSlice.cpp
25  *
26  * Created on: Apr 5, 2014
27  * Author: Yulei Sui
28  */
29 
30 #include "SABER/ProgSlice.h"
31 
32 using namespace SVF;
33 using namespace SVFUtil;
34 
44 {
45  const SVFGNode* source = getSource();
46  VFWorkList worklist;
47  worklist.push(source);
49  setVFCond(source,getTrueCond());
50 
51  while(!worklist.empty())
52  {
53  const SVFGNode* node = worklist.pop();
54  setCurSVFGNode(node);
55 
56  Condition invalidCond = computeInvalidCondFromRemovedSUVFEdge(node);
57  Condition cond = getVFCond(node);
58  for(SVFGNode::const_iterator it = node->OutEdgeBegin(), eit = node->OutEdgeEnd(); it!=eit; ++it)
59  {
60  const SVFGEdge* edge = (*it);
61  const SVFGNode* succ = edge->getDstNode();
62  if(inBackwardSlice(succ))
63  {
64  Condition vfCond;
65  const SVFBasicBlock* nodeBB = getSVFGNodeBB(node);
66  const SVFBasicBlock* succBB = getSVFGNodeBB(succ);
68  clearCFCond();
69 
70  if(edge->isCallVFGEdge())
71  {
72  vfCond = ComputeInterCallVFGGuard(nodeBB,succBB, getCallSite(edge)->getParent());
73  }
74  else if(edge->isRetVFGEdge())
75  {
76  vfCond = ComputeInterRetVFGGuard(nodeBB,succBB, getRetSite(edge)->getParent());
77  }
78  else
79  vfCond = ComputeIntraVFGGuard(nodeBB,succBB);
80  vfCond = condAnd(vfCond, condNeg(invalidCond));
81  Condition succPathCond = condAnd(cond, vfCond);
82  if(setVFCond(succ, condOr(getVFCond(succ), succPathCond) ))
83  worklist.push(succ);
84  }
85 
86  DBOUT(DSaber, outs() << " node (" << node->getId() <<
87  ") --> " << "succ (" << succ->getId() << ") condition: " << getVFCond(succ) << "\n");
88  }
89  }
90 
91  return isSatisfiableForAll();
92 }
93 
109 {
110  Set<const SVFBasicBlock*> validOutBBs; // the BBs of valid successors
111  for(SVFGNode::const_iterator it = cur->OutEdgeBegin(), eit = cur->OutEdgeEnd(); it!=eit; ++it)
112  {
113  const SVFGEdge* edge = (*it);
114  const SVFGNode* succ = edge->getDstNode();
115  if(inBackwardSlice(succ))
116  {
117  validOutBBs.insert(getSVFGNodeBB(succ));
118  }
119  }
120  Condition invalidCond = getFalseCond();
121  auto suVFEdgesIt = getRemovedSUVFEdges().find(cur);
122  if (suVFEdgesIt != getRemovedSUVFEdges().end())
123  {
124  for (const auto &succ: suVFEdgesIt->second)
125  {
126  if (!validOutBBs.count(getSVFGNodeBB(succ)))
127  {
128  // removed vfg node does not reside in the BBs of valid successors
129  const SVFBasicBlock *nodeBB = getSVFGNodeBB(cur);
130  const SVFBasicBlock *succBB = getSVFGNodeBB(succ);
131  clearCFCond();
132  invalidCond = condOr(invalidCond, ComputeIntraVFGGuard(nodeBB, succBB));
133  }
134  }
135  }
136  return invalidCond;
137 }
138 
143 {
144 
145  Condition guard = getFalseCond();
146  for(SVFGNodeSetIter it = sinksBegin(), eit = sinksEnd(); it!=eit; ++it)
147  {
148  guard = condOr(guard,getVFCond(*it));
149  }
150  setFinalCond(guard);
151 
152  return pathAllocator->isAllPathReachable(guard);
153 }
154 
159 {
160 
161  for(SVFGNodeSetIter it = sinksBegin(), eit = sinksEnd(); it!=eit; ++it)
162  {
163  for(SVFGNodeSetIter sit = it, esit = sinksEnd(); sit!=esit; ++sit)
164  {
165  if(*it == *sit)
166  continue;
167  Condition guard = condAnd(getVFCond(*sit),getVFCond(*it));
168  if(!isEquivalentBranchCond(guard, getFalseCond()))
169  {
170  setFinalCond(guard);
171  return false;
172  }
173  }
174  }
175 
176  return true;
177 }
178 
180 {
181  assert(edge->isCallVFGEdge() && "not a call svfg edge?");
182  if(const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge))
183  return getSVFG()->getCallSite(callEdge->getCallSiteId());
184  else
185  return getSVFG()->getCallSite(SVFUtil::cast<CallIndSVFGEdge>(edge)->getCallSiteId());
186 }
187 const CallICFGNode* ProgSlice::getRetSite(const SVFGEdge* edge) const
188 {
189  assert(edge->isRetVFGEdge() && "not a return svfg edge?");
190  if(const RetDirSVFGEdge* callEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge))
191  return getSVFG()->getCallSite(callEdge->getCallSiteId());
192  else
193  return getSVFG()->getCallSite(SVFUtil::cast<RetIndSVFGEdge>(edge)->getCallSiteId());
194 }
195 
197 {
198  NodeBS elems = pathAllocator->exactCondElem(finalCond);
199  for(NodeBS::iterator it = elems.begin(), eit = elems.end(); it!=eit; ++it)
200  {
201  const ICFGNode* tinst = pathAllocator->getCondInst(*it);
202  if(pathAllocator->isNegCond(*it))
203  eventStack.push_back(SVFBugEvent(
204  SVFBugEvent::Branch|((((u32_t)false) << 4) & BRANCHFLAGMASK), tinst));
205  else
206  eventStack.push_back(SVFBugEvent(
207  SVFBugEvent::Branch|((((u32_t)true) << 4) & BRANCHFLAGMASK), tinst));
208  }
209 }
210 
221 {
222  std::string str;
223  std::stringstream rawstr(str);
224  Set<std::string> locations;
225  NodeBS elems = pathAllocator->exactCondElem(finalCond);
226 
227  for(NodeBS::iterator it = elems.begin(), eit = elems.end(); it!=eit; ++it)
228  {
229  const ICFGNode* tinst = pathAllocator->getCondInst(*it);
230  if(pathAllocator->isNegCond(*it))
231  locations.insert(tinst->getSourceLoc()+"|False");
232  else
233  locations.insert(tinst->getSourceLoc()+"|True");
234  }
235 
237  for(Set<std::string>::iterator iter = locations.begin(), eiter = locations.end();
238  iter!=eiter; ++iter)
239  {
240  rawstr << "\t\t --> (" << *iter << ") \n";
241  }
242 
243  return rawstr.str();
244 }
245 
247 {
248 }
#define BRANCHFLAGMASK
Definition: SVFBugReport.h:40
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define DSaber
Definition: SVFType.h:504
const char *const string
Definition: cJSON.h:172
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
std::vector< SVFBugEvent > EventStack
Definition: SVFBugReport.h:83
NodeType * getDstNode() const
Definition: GenericGraph.h:101
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
const CallICFGNode * getRetSite(const SVFGEdge *edge) const
Definition: ProgSlice.cpp:187
void evalFinalCond2Event(GenericBug::EventStack &eventStack) const
Add final condition to eventStack.
Definition: ProgSlice.cpp:196
bool isSatisfiableForPairs()
Definition: ProgSlice.cpp:158
bool isSatisfiableForAll()
Definition: ProgSlice.cpp:142
void destroy()
Release memory.
Definition: ProgSlice.cpp:246
const CallICFGNode * getCallSite(const SVFGEdge *edge) const
Get callsite ID and get returnsiteID from SVFGEdge.
Definition: ProgSlice.cpp:179
bool AllPathReachableSolve()
Guarded reachability solve.
Definition: ProgSlice.cpp:43
Condition computeInvalidCondFromRemovedSUVFEdge(const SVFGNode *cur)
Compute invalid branch condition stemming from removed strong update value-flow edges.
Definition: ProgSlice.cpp:108
SVFGNodeSet::const_iterator SVFGNodeSetIter
Definition: ProgSlice.h:54
std::string evalFinalCond() const
Evaluate final condition.
Definition: ProgSlice.cpp:220
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
virtual const std::string getSourceLoc() const
Definition: GenericGraph.h:281
iterator end() const
iterator begin() const
bool isRetVFGEdge() const
Definition: VFGEdge.h:88
bool isCallVFGEdge() const
Definition: VFGEdge.h:84
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition: VFGNode.h:55
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96