Static Value-Flow Analysis
SrcSnkDDA.cpp
Go to the documentation of this file.
1 //===- SrcSnkDDA.cpp -- Source-sink analyzer --------------------------------//
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  * SrcSnkDDA.cpp
25  *
26  * Created on: Apr 1, 2014
27  * Author: Yulei Sui
28  */
29 
30 
31 #include "Util/Options.h"
32 #include "SABER/SrcSnkDDA.h"
33 #include "Graphs/SVFGStat.h"
34 #include "Util/Options.h"
35 #include "WPA/Andersen.h"
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
42 {
43  SVFIR* pag = PAG::getPAG();
44 
46  memSSA.setSaberCondAllocator(getSaberCondAllocator());
48  svfg = memSSA.buildFullSVFG(ander);
49  else
50  svfg = memSSA.buildPTROnlySVFG(ander);
51  setGraph(memSSA.getSVFG());
52  callgraph = ander->getCallGraph();
53  //AndersenWaveDiff::releaseAndersenWaveDiff();
55  getSaberCondAllocator()->allocate(getPAG()->getModule());
56 
57  initSrcs();
58  initSnks();
59 }
60 
62 {
63 
64  initialize(module);
65 
67 
68  for (SVFGNodeSetIter iter = sourcesBegin(), eiter = sourcesEnd();
69  iter != eiter; ++iter)
70  {
71  setCurSlice(*iter);
72 
73  DBOUT(DGENERAL, outs() << "Analysing slice:" << (*iter)->getId() << ")\n");
74  ContextCond cxt;
75  DPIm item((*iter)->getId(),cxt);
76  forwardTraverse(item);
77 
80  if (getCurSlice()->isReachGlobal())
81  {
82  DBOUT(DSaber, outs() << "Forward analysis reaches globals for slice:" << (*iter)->getId() << ")\n");
83  }
84  else
85  {
86  DBOUT(DSaber, outs() << "Forward process for slice:" << (*iter)->getId() << " (size = " << getCurSlice()->getForwardSliceSize() << ")\n");
87 
88  for (SVFGNodeSetIter sit = getCurSlice()->sinksBegin(), esit =
89  getCurSlice()->sinksEnd(); sit != esit; ++sit)
90  {
91  ContextCond cxt;
92  DPIm item((*sit)->getId(),cxt);
93  backwardTraverse(item);
94  }
95 
96  DBOUT(DSaber, outs() << "Backward process for slice:" << (*iter)->getId() << " (size = " << getCurSlice()->getBackwardSliceSize() << ")\n");
97 
98  if(Options::DumpSlice())
99  annotateSlice(_curSlice);
100 
101  if(_curSlice->AllPathReachableSolve())
102  _curSlice->setAllReachable();
103 
104  DBOUT(DSaber, outs() << "Guard computation for slice:" << (*iter)->getId() << ")\n");
105  }
106 
107  reportBug(getCurSlice());
108  }
109  finalize();
110 
111 }
112 
113 
118 bool SrcSnkDDA::isInAWrapper(const SVFGNode* src, CallSiteSet& csIdSet)
119 {
120 
121  bool reachFunExit = false;
122 
123  WorkList worklist;
124  worklist.push(src);
125  SVFGNodeBS visited;
126  u32_t step = 0;
127  while (!worklist.empty())
128  {
129  const SVFGNode* node = worklist.pop();
130 
131  if(visited.test(node->getId())==0)
132  visited.set(node->getId());
133  else
134  continue;
135  // reaching maximum steps when traversing on SVFG to identify a memory allocation wrapper
136  if (step++ > Options::MaxStepInWrapper())
137  return false;
138 
139  for (SVFGNode::const_iterator it = node->OutEdgeBegin(), eit =
140  node->OutEdgeEnd(); it != eit; ++it)
141  {
142  const SVFGEdge* edge = (*it);
143  //assert(edge->isDirectVFGEdge() && "the edge should always be direct VF");
144  // if this is a call edge
145  if(edge->isCallDirectVFGEdge())
146  {
147  return false;
148  }
149  // if this is a return edge
150  else if(edge->isRetDirectVFGEdge())
151  {
152  reachFunExit = true;
153  csIdSet.insert(getSVFG()->getCallSite(SVFUtil::cast<RetDirSVFGEdge>(edge)->getCallSiteId()));
154  }
155  // (1) an intra direct edge, we will keep tracking
156  // (2) an intra indirect edge, we only track if the succ SVFGNode is a load, which means we only track one level store-load pair .
157  // (3) do not track for all other interprocedural edges.
158  else
159  {
160  const SVFGNode* succ = edge->getDstNode();
161  if(SVFUtil::isa<IntraDirSVFGEdge>(edge))
162  {
165  StoreSVFGNode>(succ))
166  {
167  worklist.push(succ);
168  }
169  }
170  else if(SVFUtil::isa<IntraIndSVFGEdge>(edge))
171  {
172  if(SVFUtil::isa<LoadSVFGNode, IntraMSSAPHISVFGNode>(succ))
173  {
174  worklist.push(succ);
175  }
176  }
177  else
178  return false;
179  }
180  }
181  }
182  if(reachFunExit)
183  return true;
184  else
185  return false;
186 }
187 
188 
193 {
194  DBOUT(DSaber,outs() << "\n##processing source: " << getCurSlice()->getSource()->getId() <<" forward propagate from (" << edge->getSrcID());
195 
196  // for indirect SVFGEdge, the propagation should follow the def-use chains
197  // points-to on the edge indicate whether the object of source node can be propagated
198 
199  const SVFGNode* dstNode = edge->getDstNode();
200  DPIm newItem(dstNode->getId(),item.getContexts());
201 
203  if(isGlobalSVFGNode(dstNode) || getCurSlice()->isReachGlobal())
204  {
205  getCurSlice()->setReachGlobal();
206  return;
207  }
208 
209 
211  // push context for calling
212  if (edge->isCallVFGEdge())
213  {
214  CallSiteID csId = 0;
215  if(const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge))
216  csId = callEdge->getCallSiteId();
217  else
218  csId = SVFUtil::cast<CallIndSVFGEdge>(edge)->getCallSiteId();
219 
220  newItem.pushContext(csId);
221  DBOUT(DSaber, outs() << " push cxt [" << csId << "] ");
222  }
223  // match context for return
224  else if (edge->isRetVFGEdge())
225  {
226  CallSiteID csId = 0;
227  if(const RetDirSVFGEdge* callEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge))
228  csId = callEdge->getCallSiteId();
229  else
230  csId = SVFUtil::cast<RetIndSVFGEdge>(edge)->getCallSiteId();
231 
232  if (newItem.matchContext(csId) == false)
233  {
234  DBOUT(DSaber, outs() << "-|-\n");
235  return;
236  }
237  DBOUT(DSaber, outs() << " pop cxt [" << csId << "] ");
238  }
239 
241  if(forwardVisited(dstNode,newItem))
242  {
243  DBOUT(DSaber,outs() << " node "<< dstNode->getId() <<" has been visited\n");
244  return;
245  }
246  else
247  addForwardVisited(dstNode, newItem);
248 
249  if(pushIntoWorklist(newItem))
250  DBOUT(DSaber,outs() << " --> " << edge->getDstID() << ", cxt size: " << newItem.getContexts().cxtSize() <<")\n");
251 
252 }
253 
258 {
259  DBOUT(DSaber,outs() << "backward propagate from (" << edge->getDstID() << " --> " << edge->getSrcID() << ")\n");
260  const SVFGNode* srcNode = edge->getSrcNode();
261  if(backwardVisited(srcNode))
262  return;
263  else
264  addBackwardVisited(srcNode);
265 
266  ContextCond cxt;
267  DPIm newItem(srcNode->getId(), cxt);
268  pushIntoWorklist(newItem);
269 }
270 
273 {
274  if(_curSlice!=nullptr)
275  {
276  delete _curSlice;
277  _curSlice = nullptr;
278  clearVisitedMap();
279  }
280 
281  _curSlice = new ProgSlice(src,getSaberCondAllocator(), getSVFG());
282 }
283 
285 {
286  getSVFG()->getStat()->addToSources(slice->getSource());
287  for(SVFGNodeSetIter it = slice->sinksBegin(), eit = slice->sinksEnd(); it!=eit; ++it )
288  getSVFG()->getStat()->addToSinks(*it);
289  for(SVFGNodeSetIter it = slice->forwardSliceBegin(), eit = slice->forwardSliceEnd(); it!=eit; ++it )
290  getSVFG()->getStat()->addToForwardSlice(*it);
291  for(SVFGNodeSetIter it = slice->backwardSliceBegin(), eit = slice->backwardSliceEnd(); it!=eit; ++it )
292  getSVFG()->getStat()->addToBackwardSlice(*it);
293 }
294 
296 {
297 
298  if(Options::DumpSlice())
299  const_cast<SVFG*>(getSVFG())->dump("Slice",true);
300 }
301 
303 {
304 
305  outs() << "Z3 Mem usage: " << getSaberCondAllocator()->getMemUsage() << "\n";
306  outs() << "Z3 Number: " << getSaberCondAllocator()->getCondNum() << "\n";
307 }
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define DGENERAL
Definition: SVFType.h:490
#define DSaber
Definition: SVFType.h:504
cJSON * item
Definition: cJSON.h:222
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:408
u32_t cxtSize() const
Get context size.
Definition: DPItem.h:260
static void setMaxCxtLen(u32_t max)
set max context limit
Definition: DPItem.h:265
const ContextCond & getContexts() const
Get context.
Definition: DPItem.h:515
void pushContext(NodeID cxt)
Push context.
Definition: DPItem.h:520
virtual bool matchContext(NodeID cxt)
Match context.
Definition: DPItem.h:526
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeID getSrcID() const
get methods of the components
Definition: GenericGraph.h:81
NodeType * getDstNode() const
Definition: GenericGraph.h:101
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
static const Option< u32_t > CxtLimit
Definition: Options.h:173
static const Option< bool > SABERFULLSVFG
Definition: Options.h:222
static const Option< u32_t > MaxStepInWrapper
Definition: Options.h:86
static const Option< bool > DumpSlice
Definition: Options.h:172
PTACallGraph * getCallGraph() const
Return call graph.
SVFGNodeSetIter sinksEnd() const
Definition: ProgSlice.h:139
SVFGNodeSetIter backwardSliceBegin() const
Definition: ProgSlice.h:111
const SVFGNode * getSource() const
root and sink operations
Definition: ProgSlice.h:123
SVFGNodeSetIter forwardSliceEnd() const
Definition: ProgSlice.h:107
SVFGNodeSetIter sinksBegin() const
Definition: ProgSlice.h:135
SVFGNodeSetIter forwardSliceBegin() const
Definition: ProgSlice.h:103
SVFGNodeSetIter backwardSliceEnd() const
Definition: ProgSlice.h:115
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
Definition: SVFG.h:66
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
bool test(unsigned Idx) const
void set(unsigned Idx)
void BWProcessIncomingEdge(const DPIm &item, SVFGEdge *edge) override
Propagate information backward without matching context, as forward analysis already did it.
Definition: SrcSnkDDA.cpp:257
Set< const CallICFGNode * > CallSiteSet
Definition: SrcSnkDDA.h:64
void annotateSlice(ProgSlice *slice)
Definition: SrcSnkDDA.cpp:284
virtual void initialize(SVFModule *module)
Initialize analysis.
Definition: SrcSnkDDA.cpp:41
void printZ3Stat()
Definition: SrcSnkDDA.cpp:302
virtual void setCurSlice(const SVFGNode *src)
Slice operations.
Definition: SrcSnkDDA.cpp:272
virtual void analyze(SVFModule *module)
Start analysis here.
Definition: SrcSnkDDA.cpp:61
void dumpSlices()
Dump SVFG with annotated slice information.
Definition: SrcSnkDDA.cpp:295
void FWProcessOutgoingEdge(const DPIm &item, SVFGEdge *edge) override
Propagate information forward by matching context.
Definition: SrcSnkDDA.cpp:192
SVFGNodeSet::const_iterator SVFGNodeSetIter
Definition: SrcSnkDDA.h:60
bool isInAWrapper(const SVFGNode *src, CallSiteSet &csIdSet)
Identify allocation wrappers.
Definition: SrcSnkDDA.cpp:118
bool isRetVFGEdge() const
Definition: VFGEdge.h:88
bool isCallVFGEdge() const
Definition: VFGEdge.h:84
bool isRetDirectVFGEdge() const
Definition: VFGEdge.h:96
bool isCallDirectVFGEdge() const
Definition: VFGEdge.h:92
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition: VFGNode.h:55
LLVM_NODISCARD bool isa(const Y &Val)
Definition: Casting.h:241
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
void dump(const SparseBitVector< ElementSize > &LHS, std::ostream &out)
unsigned u32_t
Definition: GeneralType.h:46