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.
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
- AbstractValue loadValue(const ValVar* pointer, const ICFGNode* node);
176
- void storeValue(const ValVar* pointer, const AbstractValue& val, const ICFGNode* node);
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
- private:
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
- bool mergeStatesFromPredecessors(const ICFGNode* node);
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
- /// Returns true if the branch is reachable; narrows as in-place.
227
- bool isBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
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; narrows as in-place.
245
- bool isCmpBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
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; narrows as in-place.
248
- bool isSwitchBranchFeasible(const IntraCFGEdge* edge, AbstractState& as);
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. ValVar reads currently assert(false) until the
80
- /// SVFG-backed resolution lands (see `doc/plan-full-sparse.md`); cycle
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
- // Full-sparse ValVar resolution will route through the SVFG once
93
- // implemented; fail loudly until then rather than silently inherit
94
- // semi-sparse semantics.
95
- const AbstractValue& getAbsValue(const ValVar* var, const ICFGNode* node) override;
96
- using SemiSparseAbstractInterpretation::getAbsValue;
97
-
98
- bool hasAbsValue(const ValVar* var, const ICFGNode* node) const override;
99
- using SemiSparseAbstractInterpretation::hasAbsValue;
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
- const Set<const ICFGNode*> getUseSitesOfValVar(const ValVar* var) const;
102
- const ICFGNode* getDefSiteOfValVar(const ValVar* var) const;
103
- /// Given an ObjVar and its def-site ICFGNode, find all use-site ICFGNodes
104
- /// by following outgoing IndirectSVFGEdges whose pts contains the ObjVar
105
- const Set<const ICFGNode*> getDefSiteOfObjVar(const ObjVar* obj, const ICFGNode* node) const;
106
- /// Given an ObjVar and its def-site ICFGNode, find all use-site ICFGNodes
107
- /// by following outgoing IndirectSVFGEdges whose pts contains the ObjVar
108
- const Set<const ICFGNode*> getUseSitesOfObjVar(const ObjVar* obj, const ICFGNode* node) const;
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
 
@@ -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
- std::deque<const FunObjVar*> collectProgEntryFuns();
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 = nullptr);
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 = nullptr);
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-lib",
3
- "version": "1.0.2575",
3
+ "version": "1.0.2577",
4
4
  "description": "SVF's npm support",
5
5
  "main": "index.js",
6
6
  "scripts": {