svf-tools 1.0.657 → 1.0.659
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/svf/include/CFL/CFLAlias.h +16 -2
- package/svf/include/CFL/CFLGrammar.txt +1 -1
- package/svf/include/CFL/CFLSolver.h +86 -106
- package/svf/include/Util/Options.h +4 -0
- package/svf/lib/CFL/CFLAlias.cpp +11 -13
- package/svf/lib/CFL/CFLSolver.cpp +168 -4
- package/svf/lib/SABER/SaberSVFGBuilder.cpp +33 -2
- package/svf/lib/Util/Options.cpp +15 -1
- package/svf-llvm/tools/CFL/cfl.cpp +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.659",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -51,6 +51,10 @@ public:
|
|
|
51
51
|
/// Initialize the grammar, graph, solver
|
|
52
52
|
virtual void initialize();
|
|
53
53
|
|
|
54
|
+
/// Initialize Solver
|
|
55
|
+
virtual void initializeSolver();
|
|
56
|
+
|
|
57
|
+
|
|
54
58
|
/// Print grammar and graph
|
|
55
59
|
virtual void finalize();
|
|
56
60
|
|
|
@@ -143,9 +147,19 @@ public:
|
|
|
143
147
|
POCRAlias(SVFIR* ir) : CFLAlias(ir)
|
|
144
148
|
{
|
|
145
149
|
}
|
|
150
|
+
/// Initialize POCR Solver
|
|
151
|
+
virtual void initializeSolver();
|
|
152
|
+
};
|
|
146
153
|
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
class POCRHybrid : public CFLAlias
|
|
155
|
+
{
|
|
156
|
+
public:
|
|
157
|
+
POCRHybrid(SVFIR* ir) : CFLAlias(ir)
|
|
158
|
+
{
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// Initialize POCRHybrid Solver
|
|
162
|
+
virtual void initializeSolver();
|
|
149
163
|
};
|
|
150
164
|
} // End namespace SVF
|
|
151
165
|
|
|
@@ -3,7 +3,7 @@ Start:
|
|
|
3
3
|
Terminal:
|
|
4
4
|
addr copy store load gep vgep
|
|
5
5
|
Productions:
|
|
6
|
-
F -> epsilon | F copy | addr Memflow | F store V load | store Memflow load;
|
|
6
|
+
F -> epsilon | F copy | addr Memflow | F store V load | store Memflow load | F F;
|
|
7
7
|
Fbar -> epsilon | copybar Fbar | Memflowbar addrbar | loadbar V storebar Fbar | loadbar Memflowbar storebar;
|
|
8
8
|
V -> Fbar V F | addrbar addr | gepbar_i V gep_i | gepbarpath V gep_0 | gepbar_i F gep_i | gepbar_i Fbar gep_i;
|
|
9
9
|
copy -> vgep;
|
|
@@ -40,112 +40,6 @@ namespace SVF
|
|
|
40
40
|
{
|
|
41
41
|
typedef GrammarBase::Symbol Label;
|
|
42
42
|
|
|
43
|
-
/*!
|
|
44
|
-
* Hybrid graph representation for transitive relations
|
|
45
|
-
* The implementation is based on
|
|
46
|
-
* Yuxiang Lei, Yulei Sui, Shuo Ding, and Qirun Zhang.
|
|
47
|
-
* Taming Transitive Redundancy for Context-Free Language Reachability.
|
|
48
|
-
* ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications
|
|
49
|
-
*/
|
|
50
|
-
class HybridData
|
|
51
|
-
{
|
|
52
|
-
public:
|
|
53
|
-
struct TreeNode
|
|
54
|
-
{
|
|
55
|
-
NodeID id;
|
|
56
|
-
std::unordered_set<TreeNode*> children;
|
|
57
|
-
|
|
58
|
-
TreeNode(NodeID nId) : id(nId)
|
|
59
|
-
{}
|
|
60
|
-
|
|
61
|
-
~TreeNode()
|
|
62
|
-
{
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
inline bool operator==(const TreeNode& rhs) const
|
|
66
|
-
{
|
|
67
|
-
return id == rhs.id;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
inline bool operator<(const TreeNode& rhs) const
|
|
71
|
-
{
|
|
72
|
-
return id < rhs.id;
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
public:
|
|
78
|
-
Map<NodeID, std::unordered_map<NodeID, TreeNode*>> indMap; // indMap[v][u] points to node v in tree(u)
|
|
79
|
-
|
|
80
|
-
HybridData()
|
|
81
|
-
{}
|
|
82
|
-
|
|
83
|
-
~HybridData()
|
|
84
|
-
{
|
|
85
|
-
for (auto iter1: indMap)
|
|
86
|
-
{
|
|
87
|
-
for (auto iter2: iter1.second)
|
|
88
|
-
{
|
|
89
|
-
delete iter2.second;
|
|
90
|
-
iter2.second = NULL;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
bool hasInd(NodeID src, NodeID dst)
|
|
96
|
-
{
|
|
97
|
-
auto it = indMap.find(dst);
|
|
98
|
-
if (it == indMap.end())
|
|
99
|
-
return false;
|
|
100
|
-
return (it->second.find(src) != it->second.end());
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/// Add a node dst to tree(src)
|
|
104
|
-
TreeNode* addInd(NodeID src, NodeID dst)
|
|
105
|
-
{
|
|
106
|
-
auto resIns = indMap[dst].insert(std::make_pair(src, new TreeNode(dst)));
|
|
107
|
-
if (resIns.second)
|
|
108
|
-
return resIns.first->second;
|
|
109
|
-
return nullptr;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/// Get the node dst in tree(src)
|
|
113
|
-
TreeNode* getNode(NodeID src, NodeID dst)
|
|
114
|
-
{
|
|
115
|
-
return indMap[dst][src];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/// add v into desc(x) as a child of u
|
|
119
|
-
void insertEdge(TreeNode* u, TreeNode* v)
|
|
120
|
-
{
|
|
121
|
-
u->children.insert(v);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
void addArc(NodeID src, NodeID dst)
|
|
125
|
-
{
|
|
126
|
-
if (!hasInd(src, dst))
|
|
127
|
-
{
|
|
128
|
-
for (auto iter: indMap[src])
|
|
129
|
-
{
|
|
130
|
-
meld(iter.first, getNode(iter.first, src), getNode(dst, dst));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
void meld(NodeID x, TreeNode* uNode, TreeNode* vNode)
|
|
136
|
-
{
|
|
137
|
-
TreeNode* newVNode = addInd(x, vNode->id);
|
|
138
|
-
if (!newVNode)
|
|
139
|
-
return;
|
|
140
|
-
|
|
141
|
-
insertEdge(uNode, newVNode);
|
|
142
|
-
for (TreeNode* vChild: vNode->children)
|
|
143
|
-
{
|
|
144
|
-
meld(x, newVNode, vChild);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
43
|
class CFLSolver
|
|
150
44
|
{
|
|
151
45
|
|
|
@@ -389,6 +283,92 @@ public:
|
|
|
389
283
|
|
|
390
284
|
virtual void initialize();
|
|
391
285
|
};
|
|
286
|
+
/*!
|
|
287
|
+
* Hybrid graph representation for transitive relations
|
|
288
|
+
* The implementation is based on
|
|
289
|
+
* Yuxiang Lei, Yulei Sui, Shuo Ding, and Qirun Zhang.
|
|
290
|
+
* Taming Transitive Redundancy for Context-Free Language Reachability.
|
|
291
|
+
* ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications
|
|
292
|
+
*/
|
|
293
|
+
/// Solver Utilize Hybrid Representation of Graph
|
|
294
|
+
class POCRHybridSolver : public POCRSolver
|
|
295
|
+
{
|
|
296
|
+
//Hybrid
|
|
297
|
+
//{@
|
|
298
|
+
public:
|
|
299
|
+
struct TreeNode
|
|
300
|
+
{
|
|
301
|
+
NodeID id;
|
|
302
|
+
std::unordered_set<TreeNode*> children;
|
|
303
|
+
|
|
304
|
+
TreeNode(NodeID nId) : id(nId)
|
|
305
|
+
{}
|
|
306
|
+
|
|
307
|
+
~TreeNode()
|
|
308
|
+
{
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
inline bool operator==(const TreeNode& rhs) const
|
|
312
|
+
{
|
|
313
|
+
return id == rhs.id;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
inline bool operator<(const TreeNode& rhs) const
|
|
317
|
+
{
|
|
318
|
+
return id < rhs.id;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
public:
|
|
323
|
+
Map<NodeID, std::unordered_map<NodeID, TreeNode*>> indMap; // indMap[v][u] points to node v in tree(u)
|
|
324
|
+
|
|
325
|
+
bool hasInd_h(NodeID src, NodeID dst);
|
|
326
|
+
|
|
327
|
+
/// Add a node dst to tree(src)
|
|
328
|
+
TreeNode* addInd_h(NodeID src, NodeID dst);
|
|
329
|
+
|
|
330
|
+
/// Get the node dst in tree(src)
|
|
331
|
+
TreeNode* getNode_h(NodeID src, NodeID dst)
|
|
332
|
+
{
|
|
333
|
+
return indMap[dst][src];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// add v into desc(x) as a child of u
|
|
337
|
+
void insertEdge_h(TreeNode* u, TreeNode* v)
|
|
338
|
+
{
|
|
339
|
+
u->children.insert(v);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
void addArc_h(NodeID src, NodeID dst);
|
|
343
|
+
|
|
344
|
+
void meld_h(NodeID x, TreeNode* uNode, TreeNode* vNode);
|
|
345
|
+
//@}
|
|
346
|
+
public:
|
|
347
|
+
POCRHybridSolver(CFLGraph* _graph, CFLGrammar* _grammar) : POCRSolver(_graph, _grammar)
|
|
348
|
+
{
|
|
349
|
+
}
|
|
350
|
+
/// Destructor
|
|
351
|
+
virtual ~POCRHybridSolver()
|
|
352
|
+
{
|
|
353
|
+
for (auto iter1: indMap)
|
|
354
|
+
{
|
|
355
|
+
for (auto iter2: iter1.second)
|
|
356
|
+
{
|
|
357
|
+
delete iter2.second;
|
|
358
|
+
iter2.second = NULL;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// Process CFLEdge
|
|
364
|
+
virtual void processCFLEdge(const CFLEdge* Y_edge);
|
|
365
|
+
|
|
366
|
+
virtual void initialize();
|
|
367
|
+
|
|
368
|
+
public:
|
|
369
|
+
void addArc(NodeID src, NodeID dst);
|
|
370
|
+
void meld(NodeID x, TreeNode* uNode, TreeNode* vNode);
|
|
371
|
+
};
|
|
392
372
|
}
|
|
393
373
|
|
|
394
374
|
#endif /* INCLUDE_CFL_CFLSolver_H_*/
|
|
@@ -223,6 +223,9 @@ public:
|
|
|
223
223
|
// SaberCondAllocator.cpp
|
|
224
224
|
static const Option<bool> PrintPathCond;
|
|
225
225
|
|
|
226
|
+
// SaberSVFGBuilder.cpp
|
|
227
|
+
static const Option<bool> CollectExtRetGlobals;
|
|
228
|
+
|
|
226
229
|
// SVFUtil.cpp
|
|
227
230
|
static const Option<bool> DisableWarn;
|
|
228
231
|
|
|
@@ -256,6 +259,7 @@ public:
|
|
|
256
259
|
static const Option<bool> PEGTransfer;
|
|
257
260
|
static const Option<bool> CFLSVFG;
|
|
258
261
|
static const Option<bool> POCRAlias;
|
|
262
|
+
static const Option<bool> POCRHybrid;
|
|
259
263
|
|
|
260
264
|
// Loop Analysis
|
|
261
265
|
static const Option<bool> LoopAnalysis;
|
package/svf/lib/CFL/CFLAlias.cpp
CHANGED
|
@@ -201,6 +201,11 @@ void CFLAlias::initialize()
|
|
|
201
201
|
normalizeCFLGrammar();
|
|
202
202
|
|
|
203
203
|
// Initialize sovler
|
|
204
|
+
initializeSolver();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
void CFLAlias::initializeSolver()
|
|
208
|
+
{
|
|
204
209
|
solver = new CFLSolver(graph, grammar);
|
|
205
210
|
}
|
|
206
211
|
|
|
@@ -238,19 +243,12 @@ void CFLAlias::solve()
|
|
|
238
243
|
timeOfSolving += (end - start) / TIMEINTERVAL;
|
|
239
244
|
}
|
|
240
245
|
|
|
241
|
-
void POCRAlias::
|
|
246
|
+
void POCRAlias::initializeSolver()
|
|
242
247
|
{
|
|
243
|
-
stat = new CFLStat(this);
|
|
244
|
-
|
|
245
|
-
// Build CFL Grammar
|
|
246
|
-
buildCFLGrammar();
|
|
247
|
-
|
|
248
|
-
// Build CFL Graph
|
|
249
|
-
buildCFLGraph();
|
|
250
|
-
|
|
251
|
-
// Normalize CFL Grammar
|
|
252
|
-
normalizeCFLGrammar();
|
|
253
|
-
|
|
254
|
-
// Initialize POCRSolver
|
|
255
248
|
solver = new POCRSolver(graph, grammar);
|
|
256
249
|
}
|
|
250
|
+
|
|
251
|
+
void POCRHybrid::initializeSolver()
|
|
252
|
+
{
|
|
253
|
+
solver = new POCRHybridSolver(graph, grammar);
|
|
254
|
+
}
|
|
@@ -191,15 +191,110 @@ void POCRSolver::processCFLEdge(const CFLEdge* Y_edge)
|
|
|
191
191
|
|
|
192
192
|
void POCRSolver::initialize()
|
|
193
193
|
{
|
|
194
|
-
for(auto
|
|
194
|
+
for(auto edge : graph->getCFLEdges())
|
|
195
195
|
{
|
|
196
|
-
|
|
196
|
+
pushIntoWorklist(edge);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// Foreach production X -> epsilon
|
|
200
|
+
/// add X(i,i) if not exist to E and to worklist
|
|
201
|
+
for(const Production& prod : grammar->getEpsilonProds())
|
|
202
|
+
{
|
|
203
|
+
for(auto IDMap : getSuccMap())
|
|
197
204
|
{
|
|
198
|
-
|
|
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
|
+
}
|
|
199
212
|
}
|
|
200
213
|
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
void POCRHybridSolver::processCFLEdge(const CFLEdge* Y_edge)
|
|
217
|
+
{
|
|
218
|
+
CFLNode* i = Y_edge->getSrcNode();
|
|
219
|
+
CFLNode* j = Y_edge->getDstNode();
|
|
220
|
+
|
|
221
|
+
/// For each production X -> Y
|
|
222
|
+
/// add X(i,j) if not exist to E and to worklist
|
|
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
|
+
|
|
237
|
+
/// For each production X -> Y Z
|
|
238
|
+
/// Foreach outgoing edge Z(j,k) from node j do
|
|
239
|
+
/// add X(i,k) if not exist to E and to worklist
|
|
240
|
+
if (grammar->hasProdsFromFirstRHS(Y))
|
|
241
|
+
for(const Production& prod : grammar->getProdsFromFirstRHS(Y))
|
|
242
|
+
{
|
|
243
|
+
if ((grammar->getLHSSymbol(prod) == grammar->str2Symbol("F")) && (Y == grammar->str2Symbol("F")) && (grammar->getSecondRHSSymbol(prod) == grammar->str2Symbol("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
|
+
|
|
260
|
+
/// For each production X -> Z Y
|
|
261
|
+
/// Foreach incoming edge Z(k,i) to node i do
|
|
262
|
+
/// add X(k,j) if not exist to E and to worklist
|
|
263
|
+
if(grammar->hasProdsFromSecondRHS(Y))
|
|
264
|
+
for(const Production& prod : grammar->getProdsFromSecondRHS(Y))
|
|
265
|
+
{
|
|
266
|
+
if ((grammar->getLHSSymbol(prod) == grammar->str2Symbol("F")) && (Y == grammar->str2Symbol("F")) && (grammar->getFirstRHSSymbol(prod) == grammar->str2Symbol("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
|
+
|
|
284
|
+
void POCRHybridSolver::initialize()
|
|
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
|
+
}
|
|
201
297
|
|
|
202
|
-
/// Foreach production X -> epsilon
|
|
203
298
|
/// add X(i,i) if not exist to E and to worklist
|
|
204
299
|
for(const Production& prod : grammar->getEpsilonProds())
|
|
205
300
|
{
|
|
@@ -214,4 +309,73 @@ void POCRSolver::initialize()
|
|
|
214
309
|
}
|
|
215
310
|
}
|
|
216
311
|
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
void POCRHybridSolver::addArc(NodeID src, NodeID dst)
|
|
315
|
+
{
|
|
316
|
+
if(hasEdge(src, dst, grammar->str2Symbol("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
|
+
|
|
326
|
+
void POCRHybridSolver::meld(NodeID x, TreeNode* uNode, TreeNode* vNode)
|
|
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
|
+
|
|
341
|
+
bool POCRHybridSolver::hasInd_h(NodeID src, NodeID dst)
|
|
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
|
+
|
|
349
|
+
POCRHybridSolver::TreeNode* POCRHybridSolver::addInd_h(NodeID src, NodeID dst)
|
|
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
|
+
|
|
359
|
+
void POCRHybridSolver::addArc_h(NodeID src, NodeID dst)
|
|
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
|
+
|
|
370
|
+
void POCRHybridSolver::meld_h(NodeID x, TreeNode* uNode, TreeNode* vNode)
|
|
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
|
+
}
|
|
217
381
|
}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
#include "SABER/SaberCheckerAPI.h"
|
|
32
32
|
#include "MemoryModel/PointerAnalysisImpl.h"
|
|
33
33
|
#include "Graphs/SVFG.h"
|
|
34
|
+
#include "Util/Options.h"
|
|
34
35
|
|
|
35
36
|
using namespace SVF;
|
|
36
37
|
using namespace SVFUtil;
|
|
@@ -99,17 +100,48 @@ void SaberSVFGBuilder::collectGlobals(BVDataPTAImpl* pta)
|
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* https://github.com/SVF-tools/SVF/issues/991
|
|
106
|
+
*
|
|
107
|
+
* Originally, this function will collect all base pointers with all their fields
|
|
108
|
+
* inside the points-to set of global variables. But if a global variable points
|
|
109
|
+
* to the pointer returned by malloc() at some program points, then all pointers
|
|
110
|
+
* returned by malloc() will be included in the global set because of the
|
|
111
|
+
* context-insensitive pointer analysis results. This will make saber abandon
|
|
112
|
+
* too many slicing thus miss potential bugs.
|
|
113
|
+
*
|
|
114
|
+
* We add an option "saber-collect-extret-globals" to control whether this function
|
|
115
|
+
* will collect external functions' returned pointers. This option is true by default,
|
|
116
|
+
* making it to be false will let saber analyze more slicing but cause performance downgrade.
|
|
117
|
+
*
|
|
118
|
+
*/
|
|
119
|
+
PointsTo& SaberSVFGBuilder::CollectPtsChain(BVDataPTAImpl* pta, NodeID id, NodeToPTSSMap& cachedPtsMap)
|
|
103
120
|
{
|
|
104
121
|
SVFIR* pag = svfg->getPAG();
|
|
105
122
|
|
|
106
123
|
NodeID baseId = pag->getBaseObjVar(id);
|
|
107
124
|
NodeToPTSSMap::iterator it = cachedPtsMap.find(baseId);
|
|
108
125
|
if(it!=cachedPtsMap.end())
|
|
126
|
+
{
|
|
109
127
|
return it->second;
|
|
128
|
+
}
|
|
110
129
|
else
|
|
111
130
|
{
|
|
112
131
|
PointsTo& pts = cachedPtsMap[baseId];
|
|
132
|
+
// base object
|
|
133
|
+
if (!Options::CollectExtRetGlobals())
|
|
134
|
+
{
|
|
135
|
+
if(pta->isFIObjNode(baseId) && pag->getGNode(baseId)->hasValue())
|
|
136
|
+
{
|
|
137
|
+
const SVFCallInst* inst = SVFUtil::dyn_cast<SVFCallInst>(pag->getGNode(baseId)->getValue());
|
|
138
|
+
if(inst && SVFUtil::isExtCall(inst))
|
|
139
|
+
{
|
|
140
|
+
return pts;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
113
145
|
pts |= pag->getFieldsAfterCollapse(baseId);
|
|
114
146
|
|
|
115
147
|
WorkList worklist;
|
|
@@ -127,7 +159,6 @@ PointsTo& SaberSVFGBuilder::CollectPtsChain(BVDataPTAImpl* pta,NodeID id, NodeTo
|
|
|
127
159
|
}
|
|
128
160
|
return pts;
|
|
129
161
|
}
|
|
130
|
-
|
|
131
162
|
}
|
|
132
163
|
|
|
133
164
|
/*!
|
package/svf/lib/Util/Options.cpp
CHANGED
|
@@ -679,6 +679,14 @@ const Option<bool> Options::PrintPathCond(
|
|
|
679
679
|
);
|
|
680
680
|
|
|
681
681
|
|
|
682
|
+
// SaberSVFGBuilder.cpp
|
|
683
|
+
const Option<bool> Options::CollectExtRetGlobals(
|
|
684
|
+
"saber-collect-extret-globals",
|
|
685
|
+
"Don't include pointers returned by external function during collecting globals",
|
|
686
|
+
true
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
|
|
682
690
|
// SVFUtil.cpp
|
|
683
691
|
const Option<bool> Options::DisableWarn(
|
|
684
692
|
"dwarn",
|
|
@@ -829,6 +837,12 @@ const Option<bool> Options::POCRAlias(
|
|
|
829
837
|
false
|
|
830
838
|
);
|
|
831
839
|
|
|
840
|
+
const Option<bool> Options::POCRHybrid(
|
|
841
|
+
"pocr-hybrid",
|
|
842
|
+
"When explicit to true, POCRHybridSolver transfer CFL graph to internal hybird graph representation.",
|
|
843
|
+
false
|
|
844
|
+
);
|
|
845
|
+
|
|
832
846
|
const Option<bool> Options::LoopAnalysis(
|
|
833
847
|
"loop-analysis",
|
|
834
848
|
"Analyze every func and get loop info and loop bounds.",
|
|
@@ -841,4 +855,4 @@ const Option<u32_t> Options::LoopBound(
|
|
|
841
855
|
1
|
|
842
856
|
);
|
|
843
857
|
|
|
844
|
-
} // namespace SVF.
|
|
858
|
+
} // namespace SVF.
|
|
@@ -59,6 +59,8 @@ int main(int argc, char ** argv)
|
|
|
59
59
|
std::unique_ptr<CFLBase> cfl;
|
|
60
60
|
if (Options::CFLSVFG())
|
|
61
61
|
cfl = std::make_unique<CFLVF>(svfir);
|
|
62
|
+
else if (Options::POCRHybrid())
|
|
63
|
+
cfl = std::make_unique<POCRHybrid>(svfir);
|
|
62
64
|
else if (Options::POCRAlias())
|
|
63
65
|
cfl = std::make_unique<POCRAlias>(svfir);
|
|
64
66
|
else
|