svf-tools 1.0.1235 → 1.0.1237
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/AE/Core/AbstractState.h +1 -1
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +29 -0
- package/svf/include/AE/Svfexe/AbstractStateManager.h +21 -2
- package/svf/include/AE/Svfexe/PreAnalysis.h +3 -3
- package/svf/lib/AE/Svfexe/AEDetector.cpp +1 -1
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +107 -13
- package/svf/lib/AE/Svfexe/AbstractStateManager.cpp +66 -0
- package/svf/lib/AE/Svfexe/PreAnalysis.cpp +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1237",
|
|
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": {
|
|
@@ -352,7 +352,7 @@ public:
|
|
|
352
352
|
/// freed addresses intact. Used when building a cycle snapshot so the
|
|
353
353
|
/// ValVar set is controlled by the caller rather than whatever was
|
|
354
354
|
/// cached at the seed node.
|
|
355
|
-
void
|
|
355
|
+
void clearValVars()
|
|
356
356
|
{
|
|
357
357
|
_varToAbsVal.clear();
|
|
358
358
|
}
|
|
@@ -149,6 +149,11 @@ public:
|
|
|
149
149
|
svfStateMgr->updateAbstractState(node, state);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
inline bool hasAbsValue(const SVFVar* var, const ICFGNode* node)
|
|
153
|
+
{
|
|
154
|
+
return svfStateMgr->hasAbstractValue(var, node);
|
|
155
|
+
}
|
|
156
|
+
|
|
152
157
|
inline const AbstractValue& getAbsValue(const SVFVar* var, const ICFGNode* node)
|
|
153
158
|
{
|
|
154
159
|
return svfStateMgr->getAbstractValue(var, node);
|
|
@@ -180,6 +185,30 @@ private:
|
|
|
180
185
|
/// Handle a WTO cycle (loop or recursive function) using widening/narrowing iteration
|
|
181
186
|
virtual void handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller = nullptr);
|
|
182
187
|
|
|
188
|
+
// ---- Semi-sparse cycle helpers ----
|
|
189
|
+
// ValVars whose def-site is inside the cycle but NOT cycle_head do not
|
|
190
|
+
// flow through cycle_head's merge in semi-sparse mode, so the around-merge
|
|
191
|
+
// widening cannot observe them. getFullCycleHeadState pulls these ValVars
|
|
192
|
+
// into a single AbstractState snapshot so widen/narrow can treat ValVars
|
|
193
|
+
// and ObjVars uniformly; after widen/narrow we scatter the ValVars back
|
|
194
|
+
// to their def-sites.
|
|
195
|
+
|
|
196
|
+
/// Build a full cycle-head AbstractState: the ObjVars currently at
|
|
197
|
+
/// cycle_head combined with every cycle ValVar pulled from its
|
|
198
|
+
/// def-site. Skips ValVars without a stored value to avoid the
|
|
199
|
+
/// top-fallback contamination. In dense mode this is equivalent to
|
|
200
|
+
/// trace[cycle_head] since ValVars already live there.
|
|
201
|
+
AbstractState getFullCycleHeadState(const ICFGCycleWTO* cycle);
|
|
202
|
+
|
|
203
|
+
/// Widen prev with cur; write the widened state to trace[cycle_head]
|
|
204
|
+
/// and scatter its ValVars back to their def-sites. Returns true
|
|
205
|
+
/// when the widened result equals prev (fixpoint).
|
|
206
|
+
bool widenCycleState(const AbstractState& prev, const AbstractState& cur,
|
|
207
|
+
const ICFGCycleWTO* cycle);
|
|
208
|
+
/// Narrow prev with cur; write the narrowed state back and scatter.
|
|
209
|
+
bool narrowCycleState(const AbstractState& prev, const AbstractState& cur,
|
|
210
|
+
const ICFGCycleWTO* cycle);
|
|
211
|
+
|
|
183
212
|
/// Handle a function body via worklist-driven WTO traversal starting from funEntry
|
|
184
213
|
void handleFunction(const ICFGNode* funEntry, const CallICFGNode* caller = nullptr);
|
|
185
214
|
|
|
@@ -66,6 +66,19 @@ public:
|
|
|
66
66
|
/// Dispatch to ValVar or ObjVar overload (checks ObjVar first due to inheritance).
|
|
67
67
|
const AbstractValue& getAbstractValue(const SVFVar* var, const ICFGNode* node);
|
|
68
68
|
|
|
69
|
+
/// Check whether a ValVar has a real stored value reachable by
|
|
70
|
+
/// getAbstractValue. Unlike getAbstractValue, this is side-effect free
|
|
71
|
+
/// and does NOT treat the final top-fallback as "present" — so callers
|
|
72
|
+
/// that plan to write the fetched value back (e.g. cycle widen/narrow)
|
|
73
|
+
/// can distinguish a genuine stored value from the top sentinel.
|
|
74
|
+
bool hasAbstractValue(const ValVar* var, const ICFGNode* node) const;
|
|
75
|
+
|
|
76
|
+
/// Check whether an ObjVar has a stored value at node.
|
|
77
|
+
bool hasAbstractValue(const ObjVar* var, const ICFGNode* node) const;
|
|
78
|
+
|
|
79
|
+
/// Dispatch to ValVar or ObjVar overload.
|
|
80
|
+
bool hasAbstractValue(const SVFVar* var, const ICFGNode* node) const;
|
|
81
|
+
|
|
69
82
|
/// Write a top-level variable's abstract value into abstractTrace[node].
|
|
70
83
|
void updateAbstractValue(const ValVar* var, const AbstractValue& val, const ICFGNode* node);
|
|
71
84
|
|
|
@@ -138,8 +151,14 @@ public:
|
|
|
138
151
|
// Direct Trace Access (for merge, fixpoint, etc.)
|
|
139
152
|
// ===----------------------------------------------------------------------===//
|
|
140
153
|
|
|
141
|
-
Map<const ICFGNode*, AbstractState>& getTrace()
|
|
142
|
-
|
|
154
|
+
Map<const ICFGNode*, AbstractState>& getTrace()
|
|
155
|
+
{
|
|
156
|
+
return abstractTrace;
|
|
157
|
+
}
|
|
158
|
+
AbstractState& operator[](const ICFGNode* node)
|
|
159
|
+
{
|
|
160
|
+
return abstractTrace[node];
|
|
161
|
+
}
|
|
143
162
|
|
|
144
163
|
// ===----------------------------------------------------------------------===//
|
|
145
164
|
// Def/Use site queries (sparsity-aware)
|
|
@@ -80,10 +80,10 @@ public:
|
|
|
80
80
|
|
|
81
81
|
/// Look up the ValVar id set of a WTO cycle. Returns nullptr if the
|
|
82
82
|
/// cycle is unknown (e.g. dense mode, where the map is never built).
|
|
83
|
-
const Set<
|
|
83
|
+
const Set<const ValVar*> getCycleValVars(const ICFGCycleWTO* cycle) const
|
|
84
84
|
{
|
|
85
85
|
auto it = cycleToValVars.find(cycle);
|
|
86
|
-
return it == cycleToValVars.end() ?
|
|
86
|
+
return it == cycleToValVars.end() ? Set<const ValVar*>() : it->second;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
private:
|
|
@@ -98,7 +98,7 @@ private:
|
|
|
98
98
|
/// Pre-computed (semi-sparse only) map from a WTO cycle to the IDs of
|
|
99
99
|
/// every ValVar whose def-site is inside that cycle, including all
|
|
100
100
|
/// nested sub-cycles. Empty in dense mode.
|
|
101
|
-
Map<const ICFGCycleWTO*, Set<
|
|
101
|
+
Map<const ICFGCycleWTO*, Set<const ValVar*>> cycleToValVars;
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
} // End namespace SVF
|
|
@@ -58,7 +58,7 @@ void BufOverflowDetector::detect(const ICFGNode* node)
|
|
|
58
58
|
const AbstractValue& lhsVal = ae.getAbsValue(gep->getLHSVar(), node);
|
|
59
59
|
const AbstractValue& rhsVal = ae.getAbsValue(gep->getRHSVar(), node);
|
|
60
60
|
updateGepObjOffsetFromBase(node, lhsVal.getAddrs(), rhsVal.getAddrs(),
|
|
61
|
-
|
|
61
|
+
ae.getStateMgr()->getGepByteOffset(gep));
|
|
62
62
|
|
|
63
63
|
const AddressValue& objAddrs = rhsVal.getAddrs();
|
|
64
64
|
for (const auto& addr : objAddrs)
|
|
@@ -205,6 +205,7 @@ bool AbstractInterpretation::mergeStatesFromPredecessors(const ICFGNode* node)
|
|
|
205
205
|
{
|
|
206
206
|
// Collect all feasible predecessor states, then merge at the end.
|
|
207
207
|
AbstractState merged;
|
|
208
|
+
bool hasFeasiblePred = false;
|
|
208
209
|
|
|
209
210
|
for (auto& edge : node->getInEdges())
|
|
210
211
|
{
|
|
@@ -218,16 +219,21 @@ bool AbstractInterpretation::mergeStatesFromPredecessors(const ICFGNode* node)
|
|
|
218
219
|
{
|
|
219
220
|
AbstractState predState = getAbsState(pred);
|
|
220
221
|
if (isBranchFeasible(intraCfgEdge, predState))
|
|
222
|
+
{
|
|
221
223
|
merged.joinWith(predState);
|
|
224
|
+
hasFeasiblePred = true;
|
|
225
|
+
}
|
|
222
226
|
}
|
|
223
227
|
else
|
|
224
228
|
{
|
|
225
229
|
merged.joinWith(getAbsState(pred));
|
|
230
|
+
hasFeasiblePred = true;
|
|
226
231
|
}
|
|
227
232
|
}
|
|
228
233
|
else if (SVFUtil::isa<CallCFGEdge>(edge))
|
|
229
234
|
{
|
|
230
235
|
merged.joinWith(getAbsState(pred));
|
|
236
|
+
hasFeasiblePred = true;
|
|
231
237
|
}
|
|
232
238
|
else if (SVFUtil::isa<RetCFGEdge>(edge))
|
|
233
239
|
{
|
|
@@ -235,6 +241,7 @@ bool AbstractInterpretation::mergeStatesFromPredecessors(const ICFGNode* node)
|
|
|
235
241
|
{
|
|
236
242
|
case TOP:
|
|
237
243
|
merged.joinWith(getAbsState(pred));
|
|
244
|
+
hasFeasiblePred = true;
|
|
238
245
|
break;
|
|
239
246
|
case WIDEN_ONLY:
|
|
240
247
|
case WIDEN_NARROW:
|
|
@@ -242,14 +249,17 @@ bool AbstractInterpretation::mergeStatesFromPredecessors(const ICFGNode* node)
|
|
|
242
249
|
const RetICFGNode* returnSite = SVFUtil::dyn_cast<RetICFGNode>(node);
|
|
243
250
|
const CallICFGNode* callSite = returnSite->getCallICFGNode();
|
|
244
251
|
if (hasAbsState(callSite))
|
|
252
|
+
{
|
|
245
253
|
merged.joinWith(getAbsState(pred));
|
|
254
|
+
hasFeasiblePred = true;
|
|
255
|
+
}
|
|
246
256
|
break;
|
|
247
257
|
}
|
|
248
258
|
}
|
|
249
259
|
}
|
|
250
260
|
}
|
|
251
261
|
|
|
252
|
-
if (
|
|
262
|
+
if (!hasFeasiblePred)
|
|
253
263
|
return false;
|
|
254
264
|
|
|
255
265
|
updateAbsState(node, merged);
|
|
@@ -859,6 +869,96 @@ void AbstractInterpretation::handleFunCall(const CallICFGNode *callNode)
|
|
|
859
869
|
/// int factorial(int n) { return n <= 1 ? 1 : n * factorial(n-1); }
|
|
860
870
|
/// factorial(5) -> returns [10000, 10000] (precise after narrowing)
|
|
861
871
|
|
|
872
|
+
// ---------------------------------------------------------------------------
|
|
873
|
+
// Semi-sparse cycle helpers
|
|
874
|
+
// ---------------------------------------------------------------------------
|
|
875
|
+
//
|
|
876
|
+
// In semi-sparse mode, ValVars live at their def-sites and do not flow
|
|
877
|
+
// through the cycle-head merge. The around-merge widening at cycle_head
|
|
878
|
+
// therefore cannot observe ValVar growth across iterations (e.g. an
|
|
879
|
+
// ArgValVar that a recursive CallPE keeps overwriting at the FunEntry).
|
|
880
|
+
//
|
|
881
|
+
// To fix that, handleLoopOrRecursion runs an extra cross-iter widening on
|
|
882
|
+
// a snapshot that pulls every cycle ValVar into cycle_head's state. The set
|
|
883
|
+
// of ValVar IDs per cycle is precomputed once after PreAnalysis::initWTO()
|
|
884
|
+
// (initCycleValVars), bottom-up so nested cycles are handled before their
|
|
885
|
+
// enclosing cycle.
|
|
886
|
+
|
|
887
|
+
// --- Cycle state helpers (dense/sparse unified) ---
|
|
888
|
+
|
|
889
|
+
AbstractState AbstractInterpretation::getFullCycleHeadState(const ICFGCycleWTO* cycle)
|
|
890
|
+
{
|
|
891
|
+
const ICFGNode* cycle_head = cycle->head()->getICFGNode();
|
|
892
|
+
AbstractState snap;
|
|
893
|
+
if (hasAbsState(cycle_head))
|
|
894
|
+
snap = getAbsState(cycle_head);
|
|
895
|
+
|
|
896
|
+
if (Options::AESparsity() == AESparsity::SemiSparse)
|
|
897
|
+
{
|
|
898
|
+
const Set<const ValVar*>& valVars = preAnalysis->getCycleValVars(cycle);
|
|
899
|
+
if (valVars.empty())
|
|
900
|
+
return snap; // dense path / no cycle ValVars: snap is already complete
|
|
901
|
+
|
|
902
|
+
// Semi-sparse: drop any stale ValVar entries cached at cycle_head and
|
|
903
|
+
// pull each cycle ValVar from its def-site. ValVars without a stored
|
|
904
|
+
// value are skipped to avoid the top-fallback contamination.
|
|
905
|
+
snap.clearValVars();
|
|
906
|
+
for (const ValVar* v : valVars)
|
|
907
|
+
{
|
|
908
|
+
const ICFGNode* defSite = v->getICFGNode();
|
|
909
|
+
if (!defSite || !hasAbsValue(v, defSite)) continue;
|
|
910
|
+
snap[v->getId()] = getAbsValue(v, defSite);
|
|
911
|
+
}
|
|
912
|
+
return snap;
|
|
913
|
+
}
|
|
914
|
+
else
|
|
915
|
+
{
|
|
916
|
+
return snap;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
bool AbstractInterpretation::widenCycleState(
|
|
922
|
+
const AbstractState& prev, const AbstractState& cur, const ICFGCycleWTO* cycle)
|
|
923
|
+
{
|
|
924
|
+
AbstractState prev_copy = prev;
|
|
925
|
+
AbstractState next = prev_copy.widening(cur);
|
|
926
|
+
// Always write back (even at fixpoint) so cycle_head's trace holds the
|
|
927
|
+
// widened state for the upcoming narrowing phase.
|
|
928
|
+
const ICFGNode* cycle_head = cycle->head()->getICFGNode();
|
|
929
|
+
svfStateMgr->getTrace()[cycle_head] = next;
|
|
930
|
+
if (Options::AESparsity() == AESparsity::SemiSparse)
|
|
931
|
+
{
|
|
932
|
+
for (const auto& [id, val] : next.getVarToVal())
|
|
933
|
+
{
|
|
934
|
+
updateAbsValue(svfir->getSVFVar(id), val, cycle_head);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return next == prev;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
bool AbstractInterpretation::narrowCycleState(
|
|
941
|
+
const AbstractState& prev, const AbstractState& cur, const ICFGCycleWTO* cycle)
|
|
942
|
+
{
|
|
943
|
+
const ICFGNode* cycle_head = cycle->head()->getICFGNode();
|
|
944
|
+
if (!shouldApplyNarrowing(cycle_head->getFun()))
|
|
945
|
+
return true;
|
|
946
|
+
AbstractState prev_copy = prev;
|
|
947
|
+
AbstractState next = prev_copy.narrowing(cur);
|
|
948
|
+
if (next == prev)
|
|
949
|
+
return true; // fixpoint
|
|
950
|
+
svfStateMgr->getTrace()[cycle_head] = next;
|
|
951
|
+
if (Options::AESparsity() == AESparsity::SemiSparse)
|
|
952
|
+
{
|
|
953
|
+
for (const auto& [id, val] : next.getVarToVal())
|
|
954
|
+
{
|
|
955
|
+
updateAbsValue(svfir->getSVFVar(id), val, cycle_head);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
|
|
862
962
|
void AbstractInterpretation::handleLoopOrRecursion(const ICFGCycleWTO* cycle, const CallICFGNode* caller)
|
|
863
963
|
{
|
|
864
964
|
const ICFGNode* cycle_head = cycle->head()->getICFGNode();
|
|
@@ -874,35 +974,29 @@ void AbstractInterpretation::handleLoopOrRecursion(const ICFGCycleWTO* cycle, co
|
|
|
874
974
|
// Iterate until fixpoint with widening/narrowing on the cycle head.
|
|
875
975
|
bool increasing = true;
|
|
876
976
|
u32_t widen_delay = Options::WidenDelay();
|
|
877
|
-
auto& abstractTrace = svfStateMgr->getTrace();
|
|
878
977
|
for (u32_t cur_iter = 0;; cur_iter++)
|
|
879
978
|
{
|
|
880
979
|
if (cur_iter >= widen_delay)
|
|
881
980
|
{
|
|
882
|
-
//
|
|
883
|
-
|
|
981
|
+
// getFullCycleHeadState handles dense (returns trace[cycle_head])
|
|
982
|
+
// and semi-sparse (collects ValVars from def-sites) uniformly.
|
|
983
|
+
AbstractState prev = getFullCycleHeadState(cycle);
|
|
884
984
|
|
|
885
|
-
// Process cycle head: merge from predecessors, then execute statements
|
|
886
985
|
if (mergeStatesFromPredecessors(cycle_head))
|
|
887
986
|
handleICFGNode(cycle_head);
|
|
888
|
-
AbstractState
|
|
987
|
+
AbstractState cur = getFullCycleHeadState(cycle);
|
|
889
988
|
|
|
890
989
|
if (increasing)
|
|
891
990
|
{
|
|
892
|
-
|
|
893
|
-
if (abstractTrace[cycle_head] == prev_head_state)
|
|
991
|
+
if (widenCycleState(prev, cur, cycle))
|
|
894
992
|
{
|
|
895
|
-
// Widening fixpoint reached; switch to narrowing phase.
|
|
896
993
|
increasing = false;
|
|
897
994
|
continue;
|
|
898
995
|
}
|
|
899
996
|
}
|
|
900
997
|
else
|
|
901
998
|
{
|
|
902
|
-
if (
|
|
903
|
-
break;
|
|
904
|
-
abstractTrace[cycle_head] = prev_head_state.narrowing(cur_head_state);
|
|
905
|
-
if (abstractTrace[cycle_head] == prev_head_state)
|
|
999
|
+
if (narrowCycleState(prev, cur, cycle))
|
|
906
1000
|
break;
|
|
907
1001
|
}
|
|
908
1002
|
}
|
|
@@ -173,6 +173,71 @@ const AbstractValue& AbstractStateManager::getAbstractValue(const SVFVar* var, c
|
|
|
173
173
|
abort();
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
// ===----------------------------------------------------------------------===//
|
|
177
|
+
// hasAbstractValue — side-effect-free existence check
|
|
178
|
+
//
|
|
179
|
+
// Mirrors the lookup chain in getAbstractValue but stops short of the
|
|
180
|
+
// top-fallback. Returns false when getAbstractValue would only be able
|
|
181
|
+
// to return top as a default.
|
|
182
|
+
// ===----------------------------------------------------------------------===//
|
|
183
|
+
|
|
184
|
+
bool AbstractStateManager::hasAbstractValue(const ValVar* var, const ICFGNode* node) const
|
|
185
|
+
{
|
|
186
|
+
// Constants are always "present" (their value is intrinsic).
|
|
187
|
+
if (SVFUtil::isa<ConstIntValVar>(var) || SVFUtil::isa<ConstFPValVar>(var) ||
|
|
188
|
+
SVFUtil::isa<ConstNullPtrValVar>(var) || SVFUtil::isa<ConstDataValVar>(var))
|
|
189
|
+
return true;
|
|
190
|
+
|
|
191
|
+
u32_t id = var->getId();
|
|
192
|
+
bool semiSparse = Options::AESparsity() == AbstractInterpretation::AESparsity::SemiSparse;
|
|
193
|
+
|
|
194
|
+
// Dense mode: stored at the current node.
|
|
195
|
+
if (!semiSparse)
|
|
196
|
+
{
|
|
197
|
+
auto it = abstractTrace.find(node);
|
|
198
|
+
if (it != abstractTrace.end() &&
|
|
199
|
+
(it->second.inVarToValTable(id) || it->second.inVarToAddrsTable(id)))
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Semi-sparse (and dense fall-through): check the def-site.
|
|
204
|
+
const ICFGNode* defNode = var->getICFGNode();
|
|
205
|
+
if (defNode)
|
|
206
|
+
{
|
|
207
|
+
auto it = abstractTrace.find(defNode);
|
|
208
|
+
if (it != abstractTrace.end() && it->second.getVarToVal().count(id))
|
|
209
|
+
return true;
|
|
210
|
+
|
|
211
|
+
// Fallback for call-result ValVars: value lives at the RetICFGNode.
|
|
212
|
+
if (const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(defNode))
|
|
213
|
+
{
|
|
214
|
+
const RetICFGNode* retNode = callNode->getRetICFGNode();
|
|
215
|
+
auto rit = abstractTrace.find(retNode);
|
|
216
|
+
if (rit != abstractTrace.end() && rit->second.getVarToVal().count(id))
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
bool AbstractStateManager::hasAbstractValue(const ObjVar* var, const ICFGNode* node) const
|
|
224
|
+
{
|
|
225
|
+
auto it = abstractTrace.find(node);
|
|
226
|
+
if (it == abstractTrace.end())
|
|
227
|
+
return false;
|
|
228
|
+
u32_t objId = var->getId();
|
|
229
|
+
return it->second.getLocToVal().count(objId) != 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
bool AbstractStateManager::hasAbstractValue(const SVFVar* var, const ICFGNode* node) const
|
|
233
|
+
{
|
|
234
|
+
if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
|
|
235
|
+
return hasAbstractValue(objVar, node);
|
|
236
|
+
if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
|
|
237
|
+
return hasAbstractValue(valVar, node);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
176
241
|
// ===----------------------------------------------------------------------===//
|
|
177
242
|
// Update Abstract Value
|
|
178
243
|
// ===----------------------------------------------------------------------===//
|
|
@@ -520,3 +585,4 @@ const ICFGNode* AbstractStateManager::getDefSiteOfObjVar(const ObjVar* obj, cons
|
|
|
520
585
|
return edge->getSrcNode();
|
|
521
586
|
return nullptr;
|
|
522
587
|
}
|
|
588
|
+
|
|
@@ -129,7 +129,7 @@ void PreAnalysis::initCycleValVars()
|
|
|
129
129
|
// map when we reach their enclosing cycle.
|
|
130
130
|
for (const ICFGCycleWTO* cycle : cycles)
|
|
131
131
|
{
|
|
132
|
-
Set<
|
|
132
|
+
Set<const ValVar*>& out = cycleToValVars[cycle];
|
|
133
133
|
|
|
134
134
|
// Gather every ICFG node in this cycle (head + body singletons).
|
|
135
135
|
// For nested sub-cycles, merge their already-computed sets instead.
|
|
@@ -154,7 +154,7 @@ void PreAnalysis::initCycleValVars()
|
|
|
154
154
|
else if (const MultiOpndStmt* m = SVFUtil::dyn_cast<MultiOpndStmt>(stmt))
|
|
155
155
|
lhs = m->getRes();
|
|
156
156
|
if (lhs)
|
|
157
|
-
out.insert(lhs
|
|
157
|
+
out.insert(lhs);
|
|
158
158
|
}
|
|
159
159
|
// FunEntryICFGNode owns ArgValVars (formal parameters) that have
|
|
160
160
|
// no defining stmt at the entry — the CallPE lives on the caller
|
|
@@ -164,7 +164,7 @@ void PreAnalysis::initCycleValVars()
|
|
|
164
164
|
{
|
|
165
165
|
for (const SVFVar* fp : fe->getFormalParms())
|
|
166
166
|
if (const ValVar* v = SVFUtil::dyn_cast<ValVar>(fp))
|
|
167
|
-
out.insert(v
|
|
167
|
+
out.insert(v);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|