Static Value-Flow Analysis
CFLSolver.cpp
Go to the documentation of this file.
1 //===----- CFLSolver.cpp -- Context-free language reachability solver--------------//
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  * CFLSolver.cpp
25  *
26  * Created on: March 5, 2022
27  * Author: Yulei Sui
28  */
29 
30 #include "CFL/CFLSolver.h"
31 
32 using namespace SVF;
33 
34 double CFLSolver::numOfChecks = 0;
35 
37 {
38  for(auto it = graph->begin(); it!= graph->end(); it++)
39  {
40  for(const CFLEdge* edge : (*it).second->getOutEdges())
41  {
42  pushIntoWorklist(edge);
43  }
44  }
45 
48  for(const Production& prod : grammar->getEpsilonProds())
49  {
50  for(auto it = graph->begin(); it!= graph->end(); it++)
51  {
52  Symbol X = grammar->getLHSSymbol(prod);
53  CFLNode* i = (*it).second;
54  if(const CFLEdge* edge = graph->addCFLEdge(i, i, X))
55  {
56  pushIntoWorklist(edge);
57  }
58  }
59  }
60 }
61 
63 {
64  CFLNode* i = Y_edge->getSrcNode();
65  CFLNode* j = Y_edge->getDstNode();
66 
69  Symbol Y = Y_edge->getEdgeKind();
71  for(const Production& prod : grammar->getProdsFromSingleRHS(Y))
72  {
73  Symbol X = grammar->getLHSSymbol(prod);
74  numOfChecks++;
75  if(const CFLEdge* newEdge = graph->addCFLEdge(i, j, X))
76  {
77  pushIntoWorklist(newEdge);
78  }
79  }
80 
85  for(const Production& prod : grammar->getProdsFromFirstRHS(Y))
86  {
87  Symbol X = grammar->getLHSSymbol(prod);
88  for(const CFLEdge* Z_edge : j->getOutEdgeWithTy(grammar->getSecondRHSSymbol(prod)))
89  {
90  CFLNode* k = Z_edge->getDstNode();
91  numOfChecks++;
92  if(const CFLEdge* newEdge = graph->addCFLEdge(i, k, X))
93  {
94  pushIntoWorklist(newEdge);
95  }
96  }
97  }
98 
103  for(const Production& prod : grammar->getProdsFromSecondRHS(Y))
104  {
105  Symbol X = grammar->getLHSSymbol(prod);
106  for(const CFLEdge* Z_edge : i->getInEdgeWithTy(grammar->getFirstRHSSymbol(prod)))
107  {
108  CFLNode* k = Z_edge->getSrcNode();
109  numOfChecks++;
110  if(const CFLEdge* newEdge = graph->addCFLEdge(k, j, X))
111  {
112  pushIntoWorklist(newEdge);
113  }
114  }
115  }
116 }
117 
118 
120 {
122  initialize();
123 
124  while(!isWorklistEmpty())
125  {
127  const CFLEdge* Y_edge = popFromWorklist();
128  processCFLEdge(Y_edge);
129  }
130 }
131 
133 {
134  for (CFLEdge* edge: graph->getCFLEdges())
135  addEdge(edge->getSrcID(), edge->getDstID(), edge->getEdgeKind());
136 }
137 
139 {
140  CFLNode* i = Y_edge->getSrcNode();
141  CFLNode* j = Y_edge->getDstNode();
142 
145  Symbol Y = Y_edge->getEdgeKind();
147  for(const Production& prod : grammar->getProdsFromSingleRHS(Y))
148  {
149  Symbol X = grammar->getLHSSymbol(prod);
150  numOfChecks++;
151  if (addEdge(i->getId(), j->getId(), X))
152  {
153  const CFLEdge* newEdge = graph->addCFLEdge(Y_edge->getSrcNode(), Y_edge->getDstNode(), X);
154  pushIntoWorklist(newEdge);
155  }
156 
157  }
158 
163  for(const Production& prod : grammar->getProdsFromFirstRHS(Y))
164  {
165  Symbol X = grammar->getLHSSymbol(prod);
166  NodeBS diffDsts = addEdges(i->getId(), getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)], X);
167  numOfChecks += getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)].count();
168  for (NodeID diffDst: diffDsts)
169  {
170  const CFLEdge* newEdge = graph->addCFLEdge(i, graph->getGNode(diffDst), X);
171  pushIntoWorklist(newEdge);
172  }
173  }
174 
179  for(const Production& prod : grammar->getProdsFromSecondRHS(Y))
180  {
181  Symbol X = grammar->getLHSSymbol(prod);
182  NodeBS diffSrcs = addEdges(getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)], j->getId(), X);
183  numOfChecks += getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)].count();
184  for (NodeID diffSrc: diffSrcs)
185  {
186  const CFLEdge* newEdge = graph->addCFLEdge(graph->getGNode(diffSrc), j, X);
187  pushIntoWorklist(newEdge);
188  }
189  }
190 }
191 
193 {
194  for(auto edge : graph->getCFLEdges())
195  {
196  pushIntoWorklist(edge);
197  }
198 
201  for(const Production& prod : grammar->getEpsilonProds())
202  {
203  for(auto IDMap : getSuccMap())
204  {
205  Symbol X = grammar->getLHSSymbol(prod);
206  if (addEdge(IDMap.first, IDMap.first, X))
207  {
208  CFLNode* i = graph->getGNode(IDMap.first);
209  const CFLEdge* newEdge = graph->addCFLEdge(i, i, X);
210  pushIntoWorklist(newEdge);
211  }
212  }
213  }
214 }
215 
217 {
218  CFLNode* i = Y_edge->getSrcNode();
219  CFLNode* j = Y_edge->getDstNode();
220 
223  Symbol Y = Y_edge->getEdgeKind();
225  for(const Production& prod : grammar->getProdsFromSingleRHS(Y))
226  {
227  Symbol X = grammar->getLHSSymbol(prod);
228  numOfChecks++;
229  if (addEdge(i->getId(), j->getId(), X))
230  {
231  const CFLEdge* newEdge = graph->addCFLEdge(Y_edge->getSrcNode(), Y_edge->getDstNode(), X);
232  pushIntoWorklist(newEdge);
233  }
234 
235  }
236 
241  for(const Production& prod : grammar->getProdsFromFirstRHS(Y))
242  {
243  if ((grammar->getLHSSymbol(prod) == grammar->strToSymbol("F")) && (Y == grammar->strToSymbol("F")) && (grammar->getSecondRHSSymbol(prod) == grammar->strToSymbol("F")))
244  {
245  addArc(i->getId(), j->getId());
246  }
247  else
248  {
249  Symbol X = grammar->getLHSSymbol(prod);
250  NodeBS diffDsts = addEdges(i->getId(), getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)], X);
251  numOfChecks += getSuccMap(j->getId())[grammar->getSecondRHSSymbol(prod)].count();
252  for (NodeID diffDst: diffDsts)
253  {
254  const CFLEdge* newEdge = graph->addCFLEdge(i, graph->getGNode(diffDst), X);
255  pushIntoWorklist(newEdge);
256  }
257  }
258  }
259 
264  for(const Production& prod : grammar->getProdsFromSecondRHS(Y))
265  {
266  if ((grammar->getLHSSymbol(prod) == grammar->strToSymbol("F")) && (Y == grammar->strToSymbol("F")) && (grammar->getFirstRHSSymbol(prod) == grammar->strToSymbol("F")))
267  {
268  addArc(i->getId(), j->getId());
269  }
270  else
271  {
272  Symbol X = grammar->getLHSSymbol(prod);
273  NodeBS diffSrcs = addEdges(getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)], j->getId(), X);
274  numOfChecks += getPredMap(i->getId())[grammar->getFirstRHSSymbol(prod)].count();
275  for (NodeID diffSrc: diffSrcs)
276  {
277  const CFLEdge* newEdge = graph->addCFLEdge(graph->getGNode(diffSrc), j, X);
278  pushIntoWorklist(newEdge);
279  }
280  }
281  }
282 }
283 
285 {
286  for(auto edge : graph->getCFLEdges())
287  {
288  pushIntoWorklist(edge);
289  }
290 
291  // init hybrid dataset
292  for (auto it = graph->begin(); it != graph->end(); ++it)
293  {
294  NodeID nId = it->first;
295  addInd_h(nId, nId);
296  }
297 
299  for(const Production& prod : grammar->getEpsilonProds())
300  {
301  for(auto IDMap : getSuccMap())
302  {
303  Symbol X = grammar->getLHSSymbol(prod);
304  if (addEdge(IDMap.first, IDMap.first, X))
305  {
306  CFLNode* i = graph->getGNode(IDMap.first);
307  const CFLEdge* newEdge = graph->addCFLEdge(i, i, X);
308  pushIntoWorklist(newEdge);
309  }
310  }
311  }
312 }
313 
315 {
316  if(hasEdge(src, dst, grammar->strToSymbol("F")))
317  return;
318 
319  for (auto& iter: indMap[src])
320  {
321  meld(iter.first, getNode_h(iter.first, src), getNode_h(dst, dst));
322  }
323 }
324 
325 
327 {
328  numOfChecks++;
329 
330  TreeNode* newVNode = addInd_h(x, vNode->id);
331  if (!newVNode)
332  return;
333 
334  insertEdge_h(uNode, newVNode);
335  for (TreeNode* vChild: vNode->children)
336  {
337  meld_h(x, newVNode, vChild);
338  }
339 }
340 
342 {
343  auto it = indMap.find(dst);
344  if (it == indMap.end())
345  return false;
346  return (it->second.find(src) != it->second.end());
347 }
348 
350 {
351  TreeNode* newNode = new TreeNode(dst);
352  auto resIns = indMap[dst].insert(std::make_pair(src, newNode));
353  if (resIns.second)
354  return resIns.first->second;
355  delete newNode;
356  return nullptr;
357 }
358 
360 {
361  if (!hasInd_h(src, dst))
362  {
363  for (auto iter: indMap[src])
364  {
365  meld_h(iter.first, getNode_h(iter.first, src), getNode_h(dst, dst));
366  }
367  }
368 }
369 
371 {
372  TreeNode* newVNode = addInd_h(x, vNode->id);
373  if (!newVNode)
374  return;
375 
376  insertEdge_h(uNode, newVNode);
377  for (TreeNode* vChild: vNode->children)
378  {
379  meld_h(x, newVNode, vChild);
380  }
381 }
const Productions & getProdsFromSingleRHS(const Symbol sym) const
Definition: CFGrammar.h:346
const Productions & getProdsFromFirstRHS(const Symbol sym) const
Definition: CFGrammar.h:353
const Productions & getProdsFromSecondRHS(const Symbol sym) const
Definition: CFGrammar.h:360
const Symbol & getFirstRHSSymbol(const Production &prod) const
Definition: CFGrammar.h:373
const Symbol & getLHSSymbol(const Production &prod) const
Definition: CFGrammar.h:368
const bool hasProdsFromFirstRHS(const Symbol sym) const
Definition: CFGrammar.h:328
const bool hasProdsFromSecondRHS(const Symbol sym) const
Definition: CFGrammar.h:340
Productions & getEpsilonProds()
Definition: CFGrammar.h:308
const Symbol & getSecondRHSSymbol(const Production &prod) const
Definition: CFGrammar.h:378
const bool hasProdsFromSingleRHS(const Symbol sym) const
Definition: CFGrammar.h:334
GEdgeKind getEdgeKind() const
Definition: CFLGraph.h:58
virtual const CFLEdge * addCFLEdge(CFLNode *src, CFLNode *dst, CFLEdge::GEdgeFlag label)
Definition: CFLGraph.cpp:47
const CFLEdgeSet & getCFLEdges() const
Definition: CFLGraph.h:199
const CFLEdge::CFLEdgeSetTy & getOutEdgeWithTy(GrammarBase::Symbol s)
Definition: CFLGraph.h:99
const CFLEdge::CFLEdgeSetTy & getInEdgeWithTy(GrammarBase::Symbol s)
Definition: CFLGraph.h:94
virtual void solve()
Start solving.
Definition: CFLSolver.cpp:119
static double numOfChecks
Definition: CFLSolver.h:52
virtual void processCFLEdge(const CFLEdge *Y_edge)
Process CFLEdge.
Definition: CFLSolver.cpp:62
virtual void initialize()
Initialize worklist.
Definition: CFLSolver.cpp:36
CFGrammar::Production Production
Definition: CFLSolver.h:49
CFGrammar * grammar
Definition: CFLSolver.h:109
const CFLEdge * popFromWorklist()
Worklist operations.
Definition: CFLSolver.h:96
virtual bool pushIntoWorklist(const CFLEdge *item)
Definition: CFLSolver.h:84
virtual bool isWorklistEmpty()
Definition: CFLSolver.h:88
CFLGraph * graph
Definition: CFLSolver.h:108
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
NodeType * getDstNode() const
Definition: GenericGraph.h:101
iterator begin()
Iterators.
Definition: GenericGraph.h:627
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
Symbol strToSymbol(const std::string str) const
Definition: CFGrammar.cpp:74
void insertEdge_h(TreeNode *u, TreeNode *v)
add v into desc(x) as a child of u
Definition: CFLSolver.h:337
virtual void initialize()
Initialize worklist.
Definition: CFLSolver.cpp:284
void meld(NodeID x, TreeNode *uNode, TreeNode *vNode)
Definition: CFLSolver.cpp:326
TreeNode * getNode_h(NodeID src, NodeID dst)
Get the node dst in tree(src)
Definition: CFLSolver.h:331
void meld_h(NodeID x, TreeNode *uNode, TreeNode *vNode)
Definition: CFLSolver.cpp:370
bool hasInd_h(NodeID src, NodeID dst)
Definition: CFLSolver.cpp:341
void addArc_h(NodeID src, NodeID dst)
Definition: CFLSolver.cpp:359
void addArc(NodeID src, NodeID dst)
Definition: CFLSolver.cpp:314
TreeNode * addInd_h(NodeID src, NodeID dst)
Add a node dst to tree(src)
Definition: CFLSolver.cpp:349
Map< NodeID, std::unordered_map< NodeID, TreeNode * > > indMap
Definition: CFLSolver.h:323
virtual void processCFLEdge(const CFLEdge *Y_edge)
Process CFLEdge.
Definition: CFLSolver.cpp:216
bool hasEdge(const NodeID src, const NodeID dst, const Label ty)
find src -> find src[ty] -> find dst in set
Definition: CFLSolver.h:248
virtual void processCFLEdge(const CFLEdge *Y_edge)
Process CFLEdge.
Definition: CFLSolver.cpp:138
NodeBS addEdges(const NodeID src, const NodeBS &dstData, const Label ty)
add edges and return the set of added edges (dst) for src
Definition: CFLSolver.h:222
DataMap & getPredMap()
Definition: CFLSolver.h:188
DataMap & getSuccMap()
Definition: CFLSolver.h:183
bool addEdge(const NodeID src, const NodeID dst, const Label ty)
Definition: CFLSolver.h:215
virtual void initialize()
Initialize worklist.
Definition: CFLSolver.cpp:192
virtual void buildCFLData()
Init CFLData.
Definition: CFLSolver.cpp:132
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55
std::unordered_set< TreeNode * > children
Definition: CFLSolver.h:302