Static Value-Flow Analysis
Loading...
Searching...
No Matches
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
32using namespace SVF;
33
34double 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();
70 if (grammar->hasProdsFromSingleRHS(Y))
71 for(const Production& prod : grammar->getProdsFromSingleRHS(Y))
72 {
73 Symbol X = grammar->getLHSSymbol(prod);
75 if(const CFLEdge* newEdge = graph->addCFLEdge(i, j, X))
76 {
77 pushIntoWorklist(newEdge);
78 }
79 }
80
84 if (grammar->hasProdsFromFirstRHS(Y))
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();
92 if(const CFLEdge* newEdge = graph->addCFLEdge(i, k, X))
93 {
94 pushIntoWorklist(newEdge);
95 }
96 }
97 }
98
102 if(grammar->hasProdsFromSecondRHS(Y))
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();
146 if (grammar->hasProdsFromSingleRHS(Y))
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
162 if (grammar->hasProdsFromFirstRHS(Y))
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
178 if(grammar->hasProdsFromSecondRHS(Y))
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();
224 if (grammar->hasProdsFromSingleRHS(Y))
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
240 if (grammar->hasProdsFromFirstRHS(Y))
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
263 if(grammar->hasProdsFromSecondRHS(Y))
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}
GEdgeKind getEdgeKind() const
Definition CFLGraph.h:57
const CFLEdge::CFLEdgeSetTy & getOutEdgeWithTy(GrammarBase::Symbol s)
Definition CFLGraph.h:98
const CFLEdge::CFLEdgeSetTy & getInEdgeWithTy(GrammarBase::Symbol s)
Definition CFLGraph.h:93
virtual void solve()
Start solving.
static double numOfChecks
Definition CFLSolver.h:53
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:50
CFGrammar::Symbol Symbol
Definition CFLSolver.h:51
CFGrammar * grammar
Definition CFLSolver.h:110
virtual bool pushIntoWorklist(const CFLEdge *item)
Definition CFLSolver.h:85
virtual bool isWorklistEmpty()
Definition CFLSolver.h:89
const CFLEdge * popFromWorklist()
Worklist operations.
Definition CFLSolver.h:97
CFLGraph * graph
Definition CFLSolver.h:109
NodeType * getSrcNode() const
NodeType * getDstNode() const
TreeNode * getNode_h(NodeID src, NodeID dst)
Get the node dst in tree(src).
Definition CFLSolver.h:332
void insertEdge_h(TreeNode *u, TreeNode *v)
add v into desc(x) as a child of u
Definition CFLSolver.h:338
virtual void initialize()
Initialize worklist.
void meld(NodeID x, TreeNode *uNode, TreeNode *vNode)
void meld_h(NodeID x, TreeNode *uNode, TreeNode *vNode)
bool hasInd_h(NodeID src, NodeID dst)
void addArc_h(NodeID src, NodeID dst)
void addArc(NodeID src, NodeID dst)
TreeNode * addInd_h(NodeID src, NodeID dst)
Add a node dst to tree(src).
Map< NodeID, std::unordered_map< NodeID, TreeNode * > > indMap
Definition CFLSolver.h:324
virtual void processCFLEdge(const CFLEdge *Y_edge)
Process CFLEdge.
bool hasEdge(const NodeID src, const NodeID dst, const Label ty)
find src -> find src[ty] -> find dst in set
Definition CFLSolver.h:249
DataMap & getPredMap()
Definition CFLSolver.h:189
virtual void processCFLEdge(const CFLEdge *Y_edge)
Process CFLEdge.
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:223
bool addEdge(const NodeID src, const NodeID dst, const Label ty)
Definition CFLSolver.h:216
DataMap & getSuccMap()
Definition CFLSolver.h:184
virtual void initialize()
Initialize worklist.
virtual void buildCFLData()
Init CFLData.
NodeID getId() const
Get ID.
Definition SVFValue.h:158
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
SparseBitVector NodeBS
Definition GeneralType.h:82
std::unordered_set< TreeNode * > children
Definition CFLSolver.h:303