Static Value-Flow Analysis
ProgSlice.h
Go to the documentation of this file.
1 //===- ProgSlice.h -- Program slicing based on SVF----------------------------//
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.h
25  *
26  * Created on: Apr 1, 2014
27  * Author: Yulei Sui
28  *
29  * The implementation is based on
30  * (1) Yulei Sui, Ding Ye, and Jingling Xue. "Static Memory Leak Detection Using Full-Sparse Value-Flow Analysis".
31  * 2012 International Symposium on Software Testing and Analysis (ISSTA'12)
32  *
33  * (2) Yulei Sui, Ding Ye, and Jingling Xue. "Detecting Memory Leaks Statically with Full-Sparse Value-Flow Analysis".
34  * IEEE Transactions on Software Engineering (TSE'14)
35  */
36 
37 #ifndef PROGSLICE_H_
38 #define PROGSLICE_H_
39 
41 #include "Util/WorkList.h"
42 #include "Graphs/SVFG.h"
43 #include "Util/DPItem.h"
44 #include "Util/SVFBugReport.h"
45 
46 namespace SVF
47 {
48 
49 class ProgSlice
50 {
51 
52 public:
54  typedef SVFGNodeSet::const_iterator SVFGNodeSetIter;
57 
60 
62 
63 
65  ProgSlice(const SVFGNode* src, SaberCondAllocator* pa, const SVFG* graph):
67  pathAllocator(pa), _curSVFGNode(nullptr), finalCond(pa->getFalseCond()), svfg(graph)
68  {
69  }
70 
72  virtual ~ProgSlice()
73  {
74  destroy();
75  }
76 
77  inline u32_t getForwardSliceSize() const
78  {
79  return forwardslice.size();
80  }
81  inline u32_t getBackwardSliceSize() const
82  {
83  return backwardslice.size();
84  }
86 
87  inline void addToForwardSlice(const SVFGNode* node)
88  {
89  forwardslice.insert(node);
90  }
91  inline void addToBackwardSlice(const SVFGNode* node)
92  {
93  backwardslice.insert(node);
94  }
95  inline bool inForwardSlice(const SVFGNode* node)
96  {
97  return forwardslice.find(node)!=forwardslice.end();
98  }
99  inline bool inBackwardSlice(const SVFGNode* node)
100  {
101  return backwardslice.find(node)!=backwardslice.end();
102  }
104  {
105  return forwardslice.begin();
106  }
108  {
109  return forwardslice.end();
110  }
112  {
113  return backwardslice.begin();
114  }
116  {
117  return backwardslice.end();
118  }
120 
122 
123  inline const SVFGNode* getSource() const
124  {
125  return root;
126  }
127  inline void addToSinks(const SVFGNode* node)
128  {
129  sinks.insert(node);
130  }
131  inline const SVFGNodeSet& getSinks() const
132  {
133  return sinks;
134  }
136  {
137  return sinks.begin();
138  }
139  inline SVFGNodeSetIter sinksEnd() const
140  {
141  return sinks.end();
142  }
143  inline void setPartialReachable()
144  {
145  partialReachable = true;
146  }
147  inline void setAllReachable()
148  {
149  fullReachable = true;
150  }
151  inline bool setReachGlobal()
152  {
153  return reachGlob = true;
154  }
155  inline bool isPartialReachable() const
156  {
157  return partialReachable || reachGlob;
158  }
159  inline bool isAllReachable() const
160  {
161  return fullReachable || reachGlob;
162  }
163  inline bool isReachGlobal() const
164  {
165  return reachGlob;
166  }
168 
170  bool AllPathReachableSolve();
171  bool isSatisfiableForAll();
172  bool isSatisfiableForPairs();
173 
175 
176  const CallICFGNode* getCallSite(const SVFGEdge* edge) const;
177  const CallICFGNode* getRetSite(const SVFGEdge* edge) const;
179 
181 
182  inline Condition condAnd(const Condition &lhs, const Condition &rhs)
183  {
184  return pathAllocator->condAnd(lhs,rhs);
185  }
186  inline Condition condOr(const Condition &lhs, const Condition &rhs)
187  {
188  return pathAllocator->condOr(lhs,rhs);
189  }
190  inline Condition condNeg(const Condition &cond)
191  {
192  return pathAllocator->condNeg(cond);
193  }
194  inline Condition getTrueCond() const
195  {
196  return pathAllocator->getTrueCond();
197  }
198  inline Condition getFalseCond() const
199  {
200  return pathAllocator->getFalseCond();
201  }
202  inline std::string dumpCond(const Condition& cond) const
203  {
204  return pathAllocator->dumpCond(cond);
205  }
207  std::string evalFinalCond() const;
209  void evalFinalCond2Event(GenericBug::EventStack &eventStack) const;
211 
212 protected:
213  inline const SVFG* getSVFG() const
214  {
215  return svfg;
216  }
217 
219  void destroy();
221  inline void clearCFCond()
222  {
225  }
226 
228 
229  inline Condition getVFCond(const SVFGNode* node) const
230  {
231  SVFGNodeToCondMap::const_iterator it = svfgNodeToCondMap.find(node);
232  if(it==svfgNodeToCondMap.end())
233  {
234  return getFalseCond();
235  }
236  return it->second;
237  }
238  inline bool setVFCond(const SVFGNode* node, const Condition &cond)
239  {
240  SVFGNodeToCondMap::iterator it = svfgNodeToCondMap.find(node);
241  // until a fixed-point is reached (condition is not changed)
242  if(it!=svfgNodeToCondMap.end() && isEquivalentBranchCond(it->second, cond))
243  return false;
244 
245  svfgNodeToCondMap[node] = cond;
246  return true;
247  }
249 
251 
253  {
254  return pathAllocator->ComputeIntraVFGGuard(src,dst);
255  }
256  inline Condition ComputeInterCallVFGGuard(const SVFBasicBlock* src, const SVFBasicBlock* dst, const SVFBasicBlock* callBB)
257  {
258  return pathAllocator->ComputeInterCallVFGGuard(src,dst,callBB);
259  }
260  inline Condition ComputeInterRetVFGGuard(const SVFBasicBlock* src, const SVFBasicBlock* dst, const SVFBasicBlock* retBB)
261  {
262  return pathAllocator->ComputeInterRetVFGGuard(src,dst,retBB);
263  }
265 
266  inline bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
267  {
268  return pathAllocator->isEquivalentBranchCond(lhs, rhs);
269  };
270 
274  inline const SVFBasicBlock* getSVFGNodeBB(const SVFGNode* node) const
275  {
276  const ICFGNode* icfgNode = node->getICFGNode();
277  if(SVFUtil::isa<NullPtrSVFGNode>(node) == false)
278  {
279  return icfgNode->getBB();
280  }
281  return nullptr;
282  }
283 
285 
286  inline const SVFGNode* getCurSVFGNode() const
287  {
288  return _curSVFGNode;
289  }
290  inline void setCurSVFGNode(const SVFGNode* node)
291  {
292  _curSVFGNode = node;
294  }
296  inline void setFinalCond(const Condition &cond)
298  {
299  finalCond = cond;
300  }
301 
304 
306  {
308  }
309 
310 private:
314  const SVFGNode* root;
318  bool reachGlob;
322  const SVFG* svfg;
323 };
324 
325 } // End namespace SVF
326 
327 #endif /* PROGSLICE_H_ */
#define false
Definition: cJSON.cpp:70
const char *const string
Definition: cJSON.h:172
std::vector< SVFBugEvent > EventStack
Definition: SVFBugReport.h:83
virtual const SVFBasicBlock * getBB() const
Return the basic block of this ICFGNode.
Definition: ICFGNode.h:82
void addToForwardSlice(const SVFGNode *node)
Forward and backward slice operations.
Definition: ProgSlice.h:87
Condition finalCond
final condition
Definition: ProgSlice.h:321
const SVFGNodeSet & getSinks() const
Definition: ProgSlice.h:131
std::string dumpCond(const Condition &cond) const
Definition: ProgSlice.h:202
bool inBackwardSlice(const SVFGNode *node)
Definition: ProgSlice.h:99
bool isReachGlobal() const
Definition: ProgSlice.h:163
const CallICFGNode * getRetSite(const SVFGEdge *edge) const
Definition: ProgSlice.cpp:187
Condition condNeg(const Condition &cond)
Definition: ProgSlice.h:190
const SVFGNodeToSVFGNodeSetMap & getRemovedSUVFEdges() const
Definition: ProgSlice.h:305
void evalFinalCond2Event(GenericBug::EventStack &eventStack) const
Add final condition to eventStack.
Definition: ProgSlice.cpp:196
SaberCondAllocator::SVFGNodeToSVFGNodeSetMap SVFGNodeToSVFGNodeSetMap
Definition: ProgSlice.h:61
SVFGNodeSetIter sinksEnd() const
Definition: ProgSlice.h:139
bool partialReachable
reachable from some paths
Definition: ProgSlice.h:316
bool isAllReachable() const
Definition: ProgSlice.h:159
const SVFG * getSVFG() const
Definition: ProgSlice.h:213
bool isPartialReachable() const
Definition: ProgSlice.h:155
bool setReachGlobal()
Definition: ProgSlice.h:151
Condition condOr(const Condition &lhs, const Condition &rhs)
Definition: ProgSlice.h:186
const SVFG * svfg
SVFG.
Definition: ProgSlice.h:322
bool isSatisfiableForPairs()
Definition: ProgSlice.cpp:158
Set< const SVFGNode * > SVFGNodeSet
Definition: ProgSlice.h:53
Condition getTrueCond() const
Definition: ProgSlice.h:194
bool inForwardSlice(const SVFGNode *node)
Definition: ProgSlice.h:95
bool isSatisfiableForAll()
Definition: ProgSlice.cpp:142
bool fullReachable
reachable from all paths
Definition: ProgSlice.h:317
FIFOWorkList< const SVFGNode * > VFWorkList
worklist for value-flow guard computation
Definition: ProgSlice.h:58
bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
Definition: ProgSlice.h:266
FIFOWorkList< const SVFBasicBlock * > CFWorkList
worklist for control-flow guard computation
Definition: ProgSlice.h:59
Condition ComputeInterCallVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *callBB)
Definition: ProgSlice.h:256
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
u32_t getBackwardSliceSize() const
Definition: ProgSlice.h:81
Condition getFalseCond() const
Definition: ProgSlice.h:198
bool AllPathReachableSolve()
Guarded reachability solve.
Definition: ProgSlice.cpp:43
SaberCondAllocator::Condition Condition
Definition: ProgSlice.h:55
u32_t getForwardSliceSize() const
Definition: ProgSlice.h:77
SaberCondAllocator * pathAllocator
path condition allocator
Definition: ProgSlice.h:319
bool reachGlob
Whether slice reach a global.
Definition: ProgSlice.h:318
SVFGNodeSet sinks
a set of sink nodes
Definition: ProgSlice.h:313
void clearCFCond()
Clear Control flow conditions before each VF computation.
Definition: ProgSlice.h:221
SVFGNodeSetIter backwardSliceBegin() const
Definition: ProgSlice.h:111
bool setVFCond(const SVFGNode *node, const Condition &cond)
Definition: ProgSlice.h:238
Condition ComputeInterRetVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *retBB)
Definition: ProgSlice.h:260
const SVFBasicBlock * getSVFGNodeBB(const SVFGNode *node) const
Definition: ProgSlice.h:274
Condition computeInvalidCondFromRemovedSUVFEdge(const SVFGNode *cur)
Compute invalid branch condition stemming from removed strong update value-flow edges.
Definition: ProgSlice.cpp:108
SVFGNodeSet forwardslice
the forward slice
Definition: ProgSlice.h:311
const SVFGNode * getSource() const
root and sink operations
Definition: ProgSlice.h:123
void addToBackwardSlice(const SVFGNode *node)
Definition: ProgSlice.h:91
Condition condAnd(const Condition &lhs, const Condition &rhs)
Condition operations.
Definition: ProgSlice.h:182
void addToSinks(const SVFGNode *node)
Definition: ProgSlice.h:127
virtual ~ProgSlice()
Destructor.
Definition: ProgSlice.h:72
const SVFGNode * root
root node on the slice
Definition: ProgSlice.h:314
Map< const SVFGNode *, Condition > SVFGNodeToCondMap
map a SVFGNode to its condition during value-flow guard computation
Definition: ProgSlice.h:56
SVFGNodeSetIter forwardSliceEnd() const
Definition: ProgSlice.h:107
SVFGNodeSet backwardslice
the backward slice
Definition: ProgSlice.h:312
SVFGNodeSetIter sinksBegin() const
Definition: ProgSlice.h:135
SVFGNodeSetIter forwardSliceBegin() const
Definition: ProgSlice.h:103
void setAllReachable()
Definition: ProgSlice.h:147
Condition ComputeIntraVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst)
Compute guards for value-flows.
Definition: ProgSlice.h:252
Condition getVFCond(const SVFGNode *node) const
Get/set VF (value-flow) and CF (control-flow) conditions.
Definition: ProgSlice.h:229
SVFGNodeSetIter backwardSliceEnd() const
Definition: ProgSlice.h:115
SVFGNodeToCondMap svfgNodeToCondMap
map a SVFGNode to its path condition starting from root
Definition: ProgSlice.h:315
void setCurSVFGNode(const SVFGNode *node)
Definition: ProgSlice.h:290
const SVFGNode * _curSVFGNode
current svfg node during guard computation
Definition: ProgSlice.h:320
SVFGNodeSet::const_iterator SVFGNodeSetIter
Definition: ProgSlice.h:54
void setFinalCond(const Condition &cond)
Set final condition after all path reachability analysis.
Definition: ProgSlice.h:297
void setPartialReachable()
Definition: ProgSlice.h:143
std::string evalFinalCond() const
Evaluate final condition.
Definition: ProgSlice.cpp:220
const SVFGNode * getCurSVFGNode() const
Get/set current SVFG node.
Definition: ProgSlice.h:286
ProgSlice(const SVFGNode *src, SaberCondAllocator *pa, const SVFG *graph)
Constructor.
Definition: ProgSlice.h:65
Definition: SVFG.h:66
std::string dumpCond(const Condition &cond) const
Map< const SVFGNode *, Set< const SVFGNode * > > SVFGNodeToSVFGNodeSetMap
Condition condOr(const Condition &lhs, const Condition &rhs)
Condition condNeg(const Condition &cond)
Condition condAnd(const Condition &lhs, const Condition &rhs)
Condition operations.
virtual Condition ComputeInterRetVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *retBB)
Condition getFalseCond() const
bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
Whether lhs and rhs are equivalent branch conditions.
SVFGNodeToSVFGNodeSetMap & getRemovedSUVFEdges()
Condition getTrueCond() const
void setCurEvalSVFGNode(const SVFGNode *node)
Set current value for branch condition evaluation.
virtual Condition ComputeInterCallVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *callBB)
virtual Condition ComputeIntraVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst)
Guard Computation for a value-flow (between two basic blocks)
virtual const ICFGNode * getICFGNode() const
Return corresponding ICFG node.
Definition: VFGNode.h:67
for isBitcode
Definition: BasicTypes.h:68
VFGNode SVFGNode
Definition: SVFG.h:43
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96