svf-lib 1.0.2575 → 1.0.2577
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/SVF-linux-x86_64/bin/ae +0 -0
- package/SVF-linux-x86_64/include/AE/Svfexe/AbstractInterpretation.h +39 -14
- package/SVF-linux-x86_64/include/AE/Svfexe/SparseAbstractInterpretation.h +78 -21
- package/SVF-linux-x86_64/lib/libSvfCore.so.3.4 +0 -0
- package/SVF-osx/include/AE/Svfexe/AbstractInterpretation.h +10 -4
- package/SVF-osx/include/Util/Options.h +1 -0
- package/SVF-osx/lib/libSvfCore.3.4.dylib +0 -0
- package/package.json +1 -1
package/SVF-linux-x86_64/bin/ae
CHANGED
|
Binary file
|
|
@@ -172,8 +172,11 @@ public:
|
|
|
172
172
|
IntervalValue getGepByteOffset(const GepStmt* gep);
|
|
173
173
|
AddressValue getGepObjAddrs(const ValVar* pointer, IntervalValue offset);
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
/// Virtual so full-sparse can layer the GepObj overlay on top.
|
|
176
|
+
virtual AbstractValue loadValue(const ValVar* pointer,
|
|
177
|
+
const ICFGNode* node);
|
|
178
|
+
virtual void storeValue(const ValVar* pointer, const AbstractValue& val,
|
|
179
|
+
const ICFGNode* node);
|
|
177
180
|
|
|
178
181
|
const SVFType* getPointeeElement(const ObjVar* var, const ICFGNode* node);
|
|
179
182
|
u32_t getAllocaInstByteSize(const AddrStmt* addr);
|
|
@@ -214,17 +217,38 @@ protected:
|
|
|
214
217
|
virtual bool narrowCycleState(const AbstractState& prev, const AbstractState& cur,
|
|
215
218
|
const ICFGCycleWTO* cycle);
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
/// Initialize abstract state for the global ICFG node and process global statements
|
|
219
|
-
virtual void handleGlobalNode();
|
|
220
|
-
|
|
220
|
+
protected:
|
|
221
221
|
/// Pull-based state merge: read abstractTrace[pred] for each predecessor,
|
|
222
222
|
/// apply branch refinement for conditional IntraCFGEdges, and join into
|
|
223
223
|
/// abstractTrace[node]. Returns true if at least one predecessor had state.
|
|
224
|
-
|
|
224
|
+
/// Virtual so full-sparse can layer per-MRSVFGNode obj pulls on top of the
|
|
225
|
+
/// base ICFG-edge merge.
|
|
226
|
+
virtual bool mergeStatesFromPredecessors(const ICFGNode* node);
|
|
227
|
+
|
|
228
|
+
/// Returns true if the branch edge is reachable under the current state.
|
|
229
|
+
/// Pure query: does not update `as` or branch refinement traces.
|
|
230
|
+
bool isBranchEdgeFeasible(const IntraCFGEdge* edge, AbstractState& as);
|
|
231
|
+
|
|
232
|
+
/// Collect branch-induced interval refinement after a feasible edge has
|
|
233
|
+
/// been selected for normal CFG-state merging.
|
|
234
|
+
void collectBranchRefinement(const IntraCFGEdge* edge, AbstractState& as);
|
|
235
|
+
|
|
236
|
+
/// Hook called by collectBranchRefinement for each obj that the
|
|
237
|
+
/// branch narrows. Default (dense/semi): MEET `narrowed` onto
|
|
238
|
+
/// obj's value (read at `loadIcfg` where sparse keeps it) and
|
|
239
|
+
/// write the result into the local `as` (per-edge predState copy)
|
|
240
|
+
/// so joinStates carries it to `succ`. FullSparse overrides to
|
|
241
|
+
/// capture into refinementTrace[succ] instead.
|
|
242
|
+
virtual void recordBranchRefinement(NodeID objId,
|
|
243
|
+
const IntervalValue& narrowed,
|
|
244
|
+
AbstractState& as,
|
|
245
|
+
const ICFGNode* loadIcfg,
|
|
246
|
+
const ICFGNode* succ);
|
|
225
247
|
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
private:
|
|
249
|
+
/// Initialize abstract state for the global ICFG node and process global
|
|
250
|
+
/// statements
|
|
251
|
+
virtual void handleGlobalNode();
|
|
228
252
|
|
|
229
253
|
/// Handle a call site node: dispatch to ext-call, direct-call, or indirect-call handling
|
|
230
254
|
virtual void handleCallSite(const ICFGNode* node);
|
|
@@ -241,11 +265,12 @@ private:
|
|
|
241
265
|
/// Dispatch an SVF statement (Addr/Binary/Cmp/Load/Store/Copy/Gep/Select/Phi/Call/Ret) to its handler
|
|
242
266
|
virtual void handleSVFStatement(const SVFStmt* stmt);
|
|
243
267
|
|
|
244
|
-
/// Returns true if the cmp-conditional branch is feasible
|
|
245
|
-
bool
|
|
268
|
+
/// Returns true if the cmp-conditional branch is feasible.
|
|
269
|
+
bool isCmpBranchEdgeFeasible(const IntraCFGEdge* edge, AbstractState& as);
|
|
246
270
|
|
|
247
|
-
/// Returns true if the switch branch is feasible
|
|
248
|
-
bool
|
|
271
|
+
/// Returns true if the switch branch is feasible.
|
|
272
|
+
bool isSwitchBranchEdgeFeasible(const IntraCFGEdge* edge,
|
|
273
|
+
AbstractState& as);
|
|
249
274
|
|
|
250
275
|
void updateStateOnAddr(const AddrStmt *addr);
|
|
251
276
|
|
|
@@ -309,4 +334,4 @@ protected:
|
|
|
309
334
|
|
|
310
335
|
bool shouldApplyNarrowing(const FunObjVar* fun);
|
|
311
336
|
};
|
|
312
|
-
}
|
|
337
|
+
} // namespace SVF
|
|
@@ -24,11 +24,15 @@
|
|
|
24
24
|
#define INCLUDE_AE_SVFEXE_SPARSEABSTRACTINTERPRETATION_H_
|
|
25
25
|
|
|
26
26
|
#include "AE/Svfexe/AbstractInterpretation.h"
|
|
27
|
+
#include <memory>
|
|
27
28
|
|
|
28
29
|
namespace SVF
|
|
29
30
|
{
|
|
30
31
|
|
|
31
32
|
class SVFG;
|
|
33
|
+
class SVFGBuilder;
|
|
34
|
+
class IndirectSVFGEdge;
|
|
35
|
+
class VFGNode;
|
|
32
36
|
|
|
33
37
|
/// Abstract Interpretation for `Options::AESparsity::SemiSparse`.
|
|
34
38
|
///
|
|
@@ -76,10 +80,8 @@ protected:
|
|
|
76
80
|
///
|
|
77
81
|
/// In full-sparse mode both ValVars and ObjVars live at their SVFG
|
|
78
82
|
/// def-sites; reads query the SVFG for the reaching-def site, writes
|
|
79
|
-
/// happen at def-sites.
|
|
80
|
-
///
|
|
81
|
-
/// helpers are inherited from the semi-sparse parent and will also need
|
|
82
|
-
/// extension for ObjVars.
|
|
83
|
+
/// happen at def-sites. See `doc/plan-full-sparse.md` for the
|
|
84
|
+
/// phase plan; Phase 1 routes ValVar and ObjVar reads through the SVFG.
|
|
83
85
|
class FullSparseAbstractInterpretation : public SemiSparseAbstractInterpretation
|
|
84
86
|
{
|
|
85
87
|
public:
|
|
@@ -89,28 +91,83 @@ public:
|
|
|
89
91
|
}
|
|
90
92
|
~FullSparseAbstractInterpretation() override;
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
protected:
|
|
95
|
+
/// Full-sparse does not merge normal value-flow state along ICFG
|
|
96
|
+
/// edges. The ICFG join carries only side-channel state that is not
|
|
97
|
+
/// represented as MemorySSA def-use flow: GepObjVar field snapshots
|
|
98
|
+
/// and `_freedAddrs`. Base/Dummy ObjVars are populated later by
|
|
99
|
+
/// pullObjValueFlows from SVFG indirect in-edges; ValVars stay at their
|
|
100
|
+
/// def-sites.
|
|
101
|
+
void joinStates(AbstractState& dst, const AbstractState& src) override;
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
///
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
///
|
|
108
|
-
|
|
103
|
+
/// After a store overwrites an ObjVar, clear any branch refinement
|
|
104
|
+
/// for that ObjVar at the store's node so stale branch constraints
|
|
105
|
+
/// don't propagate past the redefinition.
|
|
106
|
+
void storeValue(const ValVar* pointer, const AbstractValue& val,
|
|
107
|
+
const ICFGNode* node) override;
|
|
108
|
+
|
|
109
|
+
/// Thin wrapper: defer to base for ICFG-edge bookkeeping
|
|
110
|
+
/// (predecessor iteration, branch feasibility, joinStates,
|
|
111
|
+
/// updateAbsState, reachability return). For reachable nodes,
|
|
112
|
+
/// additionally run pullObjValueFlows to populate trace[node] with obj
|
|
113
|
+
/// values from SVFG def-sites.
|
|
114
|
+
bool mergeStatesFromPredecessors(const ICFGNode* node) override;
|
|
115
|
+
|
|
116
|
+
/// Capture branch narrowings into refinementTrace[succ] instead of
|
|
117
|
+
/// writing them into the local `as`: in FullSparse `as` would be
|
|
118
|
+
/// discarded by joinStates (no-op for ObjVar), so we route the
|
|
119
|
+
/// narrowing to refinementTrace and let propagateAndApplyRefinement
|
|
120
|
+
/// bake it into trace at the end of mergeStatesFromPredecessors.
|
|
121
|
+
void recordBranchRefinement(NodeID objId, const IntervalValue& narrowed,
|
|
122
|
+
AbstractState& as, const ICFGNode* loadIcfg,
|
|
123
|
+
const ICFGNode* succ) override;
|
|
124
|
+
|
|
125
|
+
private:
|
|
126
|
+
/// SVFG-pull helper: walk each VFG node's indirect SVFG in-edges
|
|
127
|
+
/// and pull obj values from upstream def-site traces into
|
|
128
|
+
/// trace[node]. Multiple sources (e.g. mphi operands) JOIN.
|
|
129
|
+
void pullObjValueFlows(const ICFGNode* node);
|
|
130
|
+
|
|
131
|
+
/// Return whether an indirect SVFG edge should be pulled into dst.
|
|
132
|
+
/// Besides branch-feasible ICFG reachability, this rejects paths where
|
|
133
|
+
/// another store to the same points-to object kills the edge's value.
|
|
134
|
+
bool isIndirectSVFGEdgeFeasible(const IndirectSVFGEdge* edge,
|
|
135
|
+
const VFGNode* dst);
|
|
136
|
+
|
|
137
|
+
/// Return whether a branch-feasible ICFG path exists from src to dst.
|
|
138
|
+
/// Conditional edges are checked with a pure branch-feasibility query,
|
|
139
|
+
/// so path probing does not create branch-refinement side effects.
|
|
140
|
+
bool isICFGPathFeasible(const ICFGNode* src, const ICFGNode* dst);
|
|
141
|
+
|
|
142
|
+
/// Return whether this intra edge is allowed by the current branch state.
|
|
143
|
+
bool isIntraEdgeBranchFeasible(const IntraCFGEdge* edge,
|
|
144
|
+
const ICFGNode* src);
|
|
145
|
+
|
|
146
|
+
/// Compose pred-inherited refinement into refinementTrace[node]
|
|
147
|
+
/// (single-pred linear copy / multi-pred intersect-JOIN; any pred
|
|
148
|
+
/// without refinement drops the inheritance), then MEET the final
|
|
149
|
+
/// refinementTrace[node] into trace[node]._addrToAbsVal so the
|
|
150
|
+
/// inherited base getAbsValue(ObjVar*, node) returns the narrowed
|
|
151
|
+
/// value directly — no read-time override or cache. Called once
|
|
152
|
+
/// per merge as the last step.
|
|
153
|
+
void propagateAndApplyRefinement(const ICFGNode* node);
|
|
154
|
+
|
|
155
|
+
/// Path-refined obj values produced by branch narrowing. Each
|
|
156
|
+
/// entry is the *interval constraint* (not effective value) so
|
|
157
|
+
/// base trace can widen/narrow independently. Cached at branch
|
|
158
|
+
/// successors by recordBranchRefinement; propagated and applied by
|
|
159
|
+
/// propagateAndApplyRefinement at the end of
|
|
160
|
+
/// mergeStatesFromPredecessors.
|
|
161
|
+
Map<const ICFGNode*, Map<NodeID, IntervalValue>> refinementTrace;
|
|
109
162
|
|
|
110
|
-
protected:
|
|
111
163
|
/// Build the SVFG on top of the semi-sparse precompute.
|
|
112
164
|
void buildSVFG();
|
|
113
165
|
|
|
166
|
+
/// Owns the SVFG (via SVFGBuilder's internal unique_ptr). Without
|
|
167
|
+
/// this, SVFGBuilder would be a local in buildSVFG() and free the
|
|
168
|
+
/// graph at scope exit, leaving `svfg` dangling.
|
|
169
|
+
std::unique_ptr<SVFGBuilder> svfgBuilder;
|
|
170
|
+
/// View pointer into svfgBuilder's graph; non-null after buildSVFG().
|
|
114
171
|
SVFG* svfg{nullptr};
|
|
115
172
|
};
|
|
116
173
|
|
|
Binary file
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
#include "AE/Svfexe/AEStat.h"
|
|
38
38
|
#include "SVFIR/SVFIR.h"
|
|
39
39
|
#include "Util/SVFBugReport.h"
|
|
40
|
+
#include "Util/WorkList.h"
|
|
40
41
|
#include "Graphs/SCC.h"
|
|
41
42
|
#include "Graphs/CallGraph.h"
|
|
42
|
-
#include <deque>
|
|
43
43
|
|
|
44
44
|
namespace SVF
|
|
45
45
|
{
|
|
@@ -94,6 +94,12 @@ public:
|
|
|
94
94
|
WIDEN_NARROW
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
+
enum AEFunEntryMode
|
|
98
|
+
{
|
|
99
|
+
MAIN,
|
|
100
|
+
NO_MAIN
|
|
101
|
+
};
|
|
102
|
+
|
|
97
103
|
virtual void runOnModule();
|
|
98
104
|
|
|
99
105
|
/// Destructor
|
|
@@ -106,7 +112,7 @@ public:
|
|
|
106
112
|
void analyzeFromAllProgEntries();
|
|
107
113
|
|
|
108
114
|
/// Get all entry point functions (functions without callers)
|
|
109
|
-
|
|
115
|
+
FIFOWorkList<const FunObjVar*> collectProgEntryFuns();
|
|
110
116
|
|
|
111
117
|
/// Factory: returns the singleton instance. The concrete class is
|
|
112
118
|
/// chosen once, on first call, from `Options::AESparsity()`:
|
|
@@ -254,10 +260,10 @@ private:
|
|
|
254
260
|
virtual void handleCallSite(const ICFGNode* node);
|
|
255
261
|
|
|
256
262
|
/// Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration
|
|
257
|
-
virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller
|
|
263
|
+
virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller);
|
|
258
264
|
|
|
259
265
|
/// Handle a function body via worklist-driven WTO traversal starting from funEntry
|
|
260
|
-
void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller
|
|
266
|
+
void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller);
|
|
261
267
|
|
|
262
268
|
/// Handle an ICFG node: execute statements; return true if state changed
|
|
263
269
|
bool handleICFGNode(const ICFGNode* node);
|
|
@@ -241,6 +241,7 @@ public:
|
|
|
241
241
|
|
|
242
242
|
// Abstract Execution
|
|
243
243
|
static const OptionMap<u32_t> AESparsity;
|
|
244
|
+
static const OptionMap<u32_t> AEFunEntry;
|
|
244
245
|
static const Option<u32_t> WidenDelay;
|
|
245
246
|
/// recursion handling mode, Default: TOP
|
|
246
247
|
static const OptionMap<u32_t> HandleRecur;
|
|
Binary file
|