svf-tools 1.0.972 → 1.0.974

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.972",
3
+ "version": "1.0.974",
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": {
@@ -46,8 +46,9 @@
46
46
  #ifndef Z3_EXAMPLE_INTERVAL_DOMAIN_H
47
47
  #define Z3_EXAMPLE_INTERVAL_DOMAIN_H
48
48
 
49
- #include "AE/Core/IntervalValue.h"
50
49
  #include "AE/Core/AbstractValue.h"
50
+ #include "AE/Core/IntervalValue.h"
51
+ #include "SVFIR/SVFVariables.h"
51
52
  #include "Util/Z3Expr.h"
52
53
 
53
54
  #include <iomanip>
@@ -79,6 +80,21 @@ public:
79
80
 
80
81
  virtual ~AbstractState() = default;
81
82
 
83
+ // getGepObjAddrs
84
+ AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset);
85
+
86
+ // initObjVar
87
+ void initObjVar(ObjVar* objVar);
88
+ // getElementIndex
89
+ IntervalValue getElementIndex(const GepStmt* gep);
90
+ // getByteOffset
91
+ IntervalValue getByteOffset(const GepStmt* gep);
92
+ // printAbstractState
93
+ // loadValue
94
+ AbstractValue loadValue(NodeID varId);
95
+ // storeValue
96
+ void storeValue(NodeID varId, AbstractValue val);
97
+
82
98
 
83
99
  /// The physical address starts with 0x7f...... + idx
84
100
  static inline u32_t getVirtualMemAddress(u32_t idx)
@@ -258,14 +274,9 @@ public:
258
274
  /// domain narrow with other, and return the narrowed domain
259
275
  AbstractState narrowing(const AbstractState&other);
260
276
 
261
- /// domain widen with other, important! other widen this.
262
- void widenWith(const AbstractState&other);
263
-
264
277
  /// domain join with other, important! other widen this.
265
278
  void joinWith(const AbstractState&other);
266
279
 
267
- /// domain narrow with other, important! other widen this.
268
- void narrowWith(const AbstractState&other);
269
280
 
270
281
  /// domain meet with other, important! other widen this.
271
282
  void meetWith(const AbstractState&other);
@@ -299,8 +310,7 @@ public:
299
310
  }
300
311
 
301
312
 
302
- /// Print values of all expressions
303
- void printExprValues(std::ostream &oss) const;
313
+ void printAbstractState() const;
304
314
 
305
315
  std::string toString() const
306
316
  {
@@ -386,9 +396,6 @@ public:
386
396
  }
387
397
 
388
398
 
389
- protected:
390
- void printTable(const VarToAbsValMap&table, std::ostream &oss) const;
391
-
392
399
  };
393
400
 
394
401
  }
@@ -29,9 +29,9 @@
29
29
  //
30
30
 
31
31
  #include "AE/Core/ICFGWTO.h"
32
- #include "AE/Svfexe/SVFIR2AbsState.h"
33
32
  #include "Util/SVFBugReport.h"
34
33
  #include "WPA/Andersen.h"
34
+ #include "AE/Core/AbstractState.h"
35
35
 
36
36
  namespace SVF
37
37
  {
@@ -137,8 +137,8 @@ protected:
137
137
  /// Global ICFGNode is handled at the entry of the program,
138
138
  virtual void handleGlobalNode();
139
139
 
140
- /// mark recursive functions by detecting SCC in callgraph
141
- void markRecursiveFuns();
140
+ /// Mark recursive functions in the call graph
141
+ void initWTO();
142
142
 
143
143
  /**
144
144
  * Check if execution state exist by merging states of predecessor nodes
@@ -146,7 +146,7 @@ protected:
146
146
  * @param curNode The ICFGNode to analyse
147
147
  * @return if this node has preceding execution state
148
148
  */
149
- bool propagateStateIfFeasible(const ICFGNode* curNode);
149
+ bool mergeStatesFromPredecessors(const ICFGNode* curNode);
150
150
 
151
151
  /**
152
152
  * Check if execution state exist at the branch edge
@@ -161,14 +161,7 @@ protected:
161
161
  *
162
162
  * @param block basic block that has one instruction or a series of instructions
163
163
  */
164
- virtual void handleWTONode(const ICFGSingletonWTO *icfgSingletonWto);
165
-
166
- /**
167
- * handle one instruction in ICFGNode
168
- *
169
- * @param node ICFGNode which has a single instruction
170
- */
171
- virtual void handleICFGNode(const ICFGNode* node);
164
+ virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto);
172
165
 
173
166
  /**
174
167
  * handle call node in ICFGNode
@@ -182,14 +175,10 @@ protected:
182
175
  *
183
176
  * @param cycle WTOCycle which has weak topo order of basic blocks and nested cycles
184
177
  */
185
- virtual void handleCycle(const ICFGCycleWTO* cycle);
178
+ virtual void handleCycleWTO(const ICFGCycleWTO* cycle);
179
+
180
+ void handleWTOComponents(const std::list<const ICFGWTOComp*>& wtoComps);
186
181
 
187
- /**
188
- * handle user defined function, ext function is not included.
189
- *
190
- * @param func SVFFunction which has a series of basic blocks
191
- */
192
- virtual void handleFunc(const SVFFunction* func);
193
182
 
194
183
  /**
195
184
  * handle SVF Statement like CmpStmt, CallStmt, GepStmt, LoadStmt, StoreStmt, etc.
@@ -332,11 +321,34 @@ protected:
332
321
  void AccessMemoryViaCallArgs(const SVF::SVFArgument *arg, SVF::FILOWorkList<const SVFValue *>& worklist, Set<const SVFValue *>& visited);
333
322
 
334
323
 
324
+ void updateStateOnAddr(const AddrStmt *addr);
325
+
326
+ void updateStateOnBinary(const BinaryOPStmt *binary);
327
+
328
+ void updateStateOnCmp(const CmpStmt *cmp);
329
+
330
+ void updateStateOnLoad(const LoadStmt *load);
331
+
332
+ void updateStateOnStore(const StoreStmt *store);
333
+
334
+ void updateStateOnCopy(const CopyStmt *copy);
335
+
336
+ void updateStateOnCall(const CallPE *callPE);
337
+
338
+ void updateStateOnRet(const RetPE *retPE);
339
+
340
+ void updateStateOnGep(const GepStmt *gep);
341
+
342
+ void updateStateOnSelect(const SelectStmt *select);
343
+
344
+ void updateStateOnPhi(const PhiStmt *phi);
345
+
346
+ IntervalValue getRangeLimitFromType(const SVFType* type);
347
+
348
+
335
349
  /// protected data members, also used in subclasses
336
350
  SVFIR* _svfir;
337
- PTACallGraph* _callgraph;
338
351
  /// Execution State, used to store the Interval Value of every SVF variable
339
- SVFIR2AbsState* _svfir2AbsState;
340
352
  AEAPI* _api{nullptr};
341
353
 
342
354
  ICFG* _icfg;
@@ -347,7 +359,6 @@ protected:
347
359
  SVFBugReport _recoder;
348
360
  std::vector<const CallICFGNode*> _callSiteStack;
349
361
  Map<const ICFGNode*, std::string> _nodeToBugInfo;
350
- AndersenWaveDiff* _ander;
351
362
  Map<const SVFFunction*, ICFGWTO*> _funcToWTO;
352
363
  Set<const SVFFunction*> _recursiveFuns;
353
364
 
@@ -363,13 +374,8 @@ private:
363
374
  virtual void indirectCallFunPass(const CallICFGNode* callNode);
364
375
 
365
376
  protected:
366
- // helper functions in handleCycle
367
- bool isFixPointAfterWidening(const ICFGNode* cycle_head,
368
- AbstractState& pre_as);
369
- bool isFixPointAfterNarrowing(const SVF::ICFGNode* cycle_head,
370
- SVF::AbstractState& pre_as);
371
377
 
372
- AbstractState& getAbsState(const ICFGNode* node)
378
+ AbstractState& getAbsStateFromTrace(const ICFGNode* node)
373
379
  {
374
380
  const ICFGNode* repNode = _icfg->getRepNode(node);
375
381
  if (_postAbsTrace.count(repNode) == 0)
@@ -382,6 +388,12 @@ protected:
382
388
  }
383
389
  }
384
390
 
391
+ bool hasAbsStateFromTrace(const ICFGNode* node)
392
+ {
393
+ const ICFGNode* repNode = _icfg->getRepNode(node);
394
+ return _postAbsTrace.count(repNode) != 0;
395
+ }
396
+
385
397
  protected:
386
398
  // there data should be shared with subclasses
387
399
  Map<std::string, std::function<void(const CallSite &)>> _func_map;
@@ -174,12 +174,23 @@ private:
174
174
  */
175
175
  virtual void handleSVFStatement(const SVFStmt *stmt) override;
176
176
 
177
- /**
178
- * handle ICFGNode regarding buffer overflow checking
179
- *
180
- * @param node ICFGNode
181
- */
182
- virtual void handleICFGNode(const SVF::ICFGNode *node) override;
177
+ // TODO: will delete later
178
+ virtual void handleSingletonWTO(const ICFGSingletonWTO *icfgSingletonWto) override
179
+ {
180
+ AbstractInterpretation::handleSingletonWTO(icfgSingletonWto);
181
+ const ICFGNode* repNode = _icfg->getRepNode(icfgSingletonWto->node());
182
+ if (_postAbsTrace.count(repNode) == 0)
183
+ {
184
+ return;
185
+ }
186
+ const std::vector<const ICFGNode*>& worklist_vec = _icfg->getSubNodes(icfgSingletonWto->node());
187
+
188
+ for (auto it = worklist_vec.begin(); it != worklist_vec.end(); ++it)
189
+ {
190
+ const ICFGNode* curNode = *it;
191
+ detectBufOverflow(curNode);
192
+ }
193
+ }
183
194
 
184
195
  /**
185
196
  * check buffer overflow at ICFGNode which is a checkpoint
@@ -27,7 +27,6 @@
27
27
  // The implementation is based on
28
28
  // Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
29
29
  // 46th International Conference on Software Engineering. (ICSE24)
30
- #include "AE/Svfexe/SVFIR2AbsState.h"
31
30
  #include "Graphs/ICFG.h"
32
31
 
33
32
  namespace SVF
@@ -209,7 +209,7 @@ class DoubleFreeBug : public GenericBug
209
209
  {
210
210
  public:
211
211
  DoubleFreeBug(const EventStack &bugEventStack):
212
- GenericBug(GenericBug::PARTIALLEAK, bugEventStack) { }
212
+ GenericBug(GenericBug::DOUBLEFREE, bugEventStack) { }
213
213
 
214
214
  cJSON *getBugDescription() const;
215
215
  void printBugToTerminal() const;
@@ -225,7 +225,7 @@ class FileNeverCloseBug : public GenericBug
225
225
  {
226
226
  public:
227
227
  FileNeverCloseBug(const EventStack &bugEventStack):
228
- GenericBug(GenericBug::NEVERFREE, bugEventStack) { };
228
+ GenericBug(GenericBug::FILENEVERCLOSE, bugEventStack) { };
229
229
 
230
230
  cJSON *getBugDescription() const;
231
231
  void printBugToTerminal() const;
@@ -241,7 +241,7 @@ class FilePartialCloseBug : public GenericBug
241
241
  {
242
242
  public:
243
243
  FilePartialCloseBug(const EventStack &bugEventStack):
244
- GenericBug(GenericBug::PARTIALLEAK, bugEventStack) { }
244
+ GenericBug(GenericBug::FILEPARTIALCLOSE, bugEventStack) { }
245
245
 
246
246
  cJSON *getBugDescription() const;
247
247
  void printBugToTerminal() const;
@@ -29,6 +29,7 @@
29
29
 
30
30
  #include "AE/Core/AbstractState.h"
31
31
  #include "Util/SVFUtil.h"
32
+ #include "Util/Options.h"
32
33
 
33
34
  using namespace SVF;
34
35
  using namespace SVFUtil;
@@ -97,25 +98,6 @@ AbstractState AbstractState::narrowing(const AbstractState& other)
97
98
 
98
99
  }
99
100
 
100
- /// domain widen with other, important! other widen this.
101
- void AbstractState::widenWith(const AbstractState& other)
102
- {
103
- for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
104
- {
105
- auto key = it->first;
106
- if (other.getVarToVal().find(key) != other.getVarToVal().end())
107
- if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
108
- it->second.getInterval().widen_with(other._varToAbsVal.at(key).getInterval());
109
- }
110
- for (auto it = _addrToAbsVal.begin(); it != _addrToAbsVal.end(); ++it)
111
- {
112
- auto key = it->first;
113
- if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
114
- if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
115
- it->second.getInterval().widen_with(other._addrToAbsVal.at(key).getInterval());
116
- }
117
- }
118
-
119
101
  /// domain join with other, important! other widen this.
120
102
  void AbstractState::joinWith(const AbstractState& other)
121
103
  {
@@ -147,27 +129,6 @@ void AbstractState::joinWith(const AbstractState& other)
147
129
  }
148
130
  }
149
131
 
150
- /// domain narrow with other, important! other widen this.
151
- void AbstractState::narrowWith(const AbstractState& other)
152
- {
153
- for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
154
- {
155
- auto key = it->first;
156
- auto oit = other.getVarToVal().find(key);
157
- if (oit != other.getVarToVal().end())
158
- if (it->second.isInterval() && oit->second.isInterval())
159
- it->second.getInterval().narrow_with(oit->second.getInterval());
160
- }
161
- for (auto it = _addrToAbsVal.begin(); it != _addrToAbsVal.end(); ++it)
162
- {
163
- auto key = it->first;
164
- auto oit = other._addrToAbsVal.find(key);
165
- if (oit != other._addrToAbsVal.end())
166
- if (it->second.isInterval() && oit->second.isInterval())
167
- it->second.getInterval().narrow_with(oit->second.getInterval());
168
- }
169
- }
170
-
171
132
  /// domain meet with other, important! other widen this.
172
133
  void AbstractState::meetWith(const AbstractState& other)
173
134
  {
@@ -191,26 +152,320 @@ void AbstractState::meetWith(const AbstractState& other)
191
152
  }
192
153
  }
193
154
 
194
- /// Print values of all expressions
195
- void AbstractState::printExprValues(std::ostream &oss) const
155
+ // getGepObjAddrs
156
+ AddressValue AbstractState::getGepObjAddrs(u32_t pointer, IntervalValue offset)
157
+ {
158
+ AddressValue gepAddrs;
159
+ APOffset lb = offset.lb().getIntNumeral() < Options::MaxFieldLimit() ? offset.lb().getIntNumeral()
160
+ : Options::MaxFieldLimit();
161
+ APOffset ub = offset.ub().getIntNumeral() < Options::MaxFieldLimit() ? offset.ub().getIntNumeral()
162
+ : Options::MaxFieldLimit();
163
+ for (APOffset i = lb; i <= ub; i++)
164
+ {
165
+ AbstractValue addrs = (*this)[pointer];
166
+ for (const auto& addr : addrs.getAddrs())
167
+ {
168
+ s64_t baseObj = AbstractState::getInternalID(addr);
169
+ assert(SVFUtil::isa<ObjVar>(PAG::getPAG()->getGNode(baseObj)) && "Fail to get the base object address!");
170
+ NodeID gepObj = PAG::getPAG()->getGepObjVar(baseObj, i);
171
+ (*this)[gepObj] = AddressValue(AbstractState::getVirtualMemAddress(gepObj));
172
+ gepAddrs.insert(AbstractState::getVirtualMemAddress(gepObj));
173
+ }
174
+ }
175
+
176
+ return gepAddrs;
177
+ }
178
+ // initObjVar
179
+ void AbstractState::initObjVar(ObjVar* objVar)
180
+ {
181
+ NodeID varId = objVar->getId();
182
+
183
+ // Check if the object variable has an associated value
184
+ if (objVar->hasValue())
185
+ {
186
+ const MemObj* obj = objVar->getMemObj();
187
+
188
+ // Handle constant data, arrays, and structures
189
+ if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
190
+ {
191
+ if (const SVFConstantInt* consInt = SVFUtil::dyn_cast<SVFConstantInt>(obj->getValue()))
192
+ {
193
+ s64_t numeral = consInt->getSExtValue();
194
+ (*this)[varId] = IntervalValue(numeral, numeral);
195
+ }
196
+ else if (const SVFConstantFP* consFP = SVFUtil::dyn_cast<SVFConstantFP>(obj->getValue()))
197
+ {
198
+ (*this)[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
199
+ }
200
+ else if (SVFUtil::isa<SVFConstantNullPtr>(obj->getValue()))
201
+ {
202
+ (*this)[varId] = IntervalValue(0, 0);
203
+ }
204
+ else if (SVFUtil::isa<SVFGlobalValue>(obj->getValue()))
205
+ {
206
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
207
+ }
208
+ else if (obj->isConstantArray() || obj->isConstantStruct())
209
+ {
210
+ (*this)[varId] = IntervalValue::top();
211
+ }
212
+ else
213
+ {
214
+ (*this)[varId] = IntervalValue::top();
215
+ }
216
+ }
217
+ // Handle non-constant memory objects
218
+ else
219
+ {
220
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
221
+ }
222
+ }
223
+ // If the object variable does not have an associated value, set it to a virtual memory address
224
+ else
225
+ {
226
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
227
+ }
228
+ return;
229
+ }
230
+
231
+ // getElementIndex
232
+ IntervalValue AbstractState::getElementIndex(const GepStmt* gep)
233
+ {
234
+ // If the GEP statement has a constant offset, return it directly as the interval value
235
+ if (gep->isConstantOffset())
236
+ return IntervalValue((s64_t)gep->accumulateConstantOffset());
237
+
238
+ IntervalValue res(0);
239
+ // Iterate over the list of offset variable and type pairs in reverse order
240
+ for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
241
+ {
242
+ AccessPath::IdxOperandPair IdxVarAndType = gep->getOffsetVarAndGepTypePairVec()[i];
243
+ const SVFValue* value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
244
+ const SVFType* type = IdxVarAndType.second;
245
+
246
+ // Variables to store the lower and upper bounds of the index value
247
+ s64_t idxLb;
248
+ s64_t idxUb;
249
+
250
+ // Determine the lower and upper bounds based on whether the value is a constant
251
+ if (const SVFConstantInt* constInt = SVFUtil::dyn_cast<SVFConstantInt>(value))
252
+ idxLb = idxUb = constInt->getSExtValue();
253
+ else
254
+ {
255
+ IntervalValue idxItv = (*this)[PAG::getPAG()->getValueNode(value)].getInterval();
256
+ if (idxItv.isBottom())
257
+ idxLb = idxUb = 0;
258
+ else
259
+ {
260
+ idxLb = idxItv.lb().getIntNumeral();
261
+ idxUb = idxItv.ub().getIntNumeral();
262
+ }
263
+ }
264
+
265
+ // Adjust the bounds if the type is a pointer
266
+ if (SVFUtil::isa<SVFPointerType>(type))
267
+ {
268
+ u32_t elemNum = gep->getAccessPath().getElementNum(gep->getAccessPath().gepSrcPointeeType());
269
+ idxLb = (double)Options::MaxFieldLimit() / elemNum < idxLb ? Options::MaxFieldLimit() : idxLb * elemNum;
270
+ idxUb = (double)Options::MaxFieldLimit() / elemNum < idxUb ? Options::MaxFieldLimit() : idxUb * elemNum;
271
+ }
272
+ // Adjust the bounds for array or struct types using the symbol table info
273
+ else
274
+ {
275
+ if (Options::ModelArrays())
276
+ {
277
+ const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
278
+ if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
279
+ {
280
+ idxLb = idxUb = 0;
281
+ }
282
+ else
283
+ {
284
+ idxLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, idxLb);
285
+ idxUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, idxUb);
286
+ }
287
+ }
288
+ else
289
+ idxLb = idxUb = 0;
290
+ }
291
+
292
+ // Add the calculated interval to the result
293
+ res = res + IntervalValue(idxLb, idxUb);
294
+ }
295
+
296
+ // Ensure the result is within the bounds of [0, MaxFieldLimit]
297
+ res.meet_with(IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit()));
298
+ if (res.isBottom())
299
+ {
300
+ res = IntervalValue(0);
301
+ }
302
+ return res;
303
+ }
304
+ // getByteOffset
305
+ IntervalValue AbstractState::getByteOffset(const GepStmt* gep)
196
306
  {
197
- oss << "-----------Var and Value-----------\n";
198
- printTable(_varToAbsVal, oss);
199
- printTable(_addrToAbsVal, oss);
200
- oss << "-----------------------------------------\n";
307
+ // If the GEP statement has a constant byte offset, return it directly as the interval value
308
+ if (gep->isConstantOffset())
309
+ return IntervalValue((s64_t)gep->accumulateConstantByteOffset());
310
+
311
+ IntervalValue res(0); // Initialize the result interval 'res' to 0.
312
+
313
+ // Loop through the offsetVarAndGepTypePairVec in reverse order.
314
+ for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
315
+ {
316
+ const SVFVar* idxOperandVar = gep->getOffsetVarAndGepTypePairVec()[i].first;
317
+ const SVFType* idxOperandType = gep->getOffsetVarAndGepTypePairVec()[i].second;
318
+
319
+ // Calculate the byte offset for array or pointer types
320
+ if (SVFUtil::isa<SVFArrayType>(idxOperandType) || SVFUtil::isa<SVFPointerType>(idxOperandType))
321
+ {
322
+ u32_t elemByteSize = 1;
323
+ if (const SVFArrayType* arrOperandType = SVFUtil::dyn_cast<SVFArrayType>(idxOperandType))
324
+ elemByteSize = arrOperandType->getTypeOfElement()->getByteSize();
325
+ else if (SVFUtil::isa<SVFPointerType>(idxOperandType))
326
+ elemByteSize = gep->getAccessPath().gepSrcPointeeType()->getByteSize();
327
+ else
328
+ assert(false && "idxOperandType must be ArrType or PtrType");
329
+
330
+ if (const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(idxOperandVar->getValue()))
331
+ {
332
+ // Calculate the lower bound (lb) of the interval value
333
+ s64_t lb = (double)Options::MaxFieldLimit() / elemByteSize >= op->getSExtValue()
334
+ ? op->getSExtValue() * elemByteSize
335
+ : Options::MaxFieldLimit();
336
+ res = res + IntervalValue(lb, lb);
337
+ }
338
+ else
339
+ {
340
+ u32_t idx = PAG::getPAG()->getValueNode(idxOperandVar->getValue());
341
+ IntervalValue idxVal = (*this)[idx].getInterval();
342
+
343
+ if (idxVal.isBottom())
344
+ res = res + IntervalValue(0, 0);
345
+ else
346
+ {
347
+ // Ensure the bounds are non-negative and within the field limit
348
+ s64_t ub = (idxVal.ub().getIntNumeral() < 0) ? 0
349
+ : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.ub().getIntNumeral()
350
+ ? elemByteSize * idxVal.ub().getIntNumeral()
351
+ : Options::MaxFieldLimit();
352
+ s64_t lb = (idxVal.lb().getIntNumeral() < 0) ? 0
353
+ : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.lb().getIntNumeral()
354
+ ? elemByteSize * idxVal.lb().getIntNumeral()
355
+ : Options::MaxFieldLimit();
356
+ res = res + IntervalValue(lb, ub);
357
+ }
358
+ }
359
+ }
360
+ // Process struct subtypes by calculating the byte offset from the beginning to the field of the struct
361
+ else if (const SVFStructType* structOperandType = SVFUtil::dyn_cast<SVFStructType>(idxOperandType))
362
+ {
363
+ res = res + IntervalValue(gep->getAccessPath().getStructFieldOffset(idxOperandVar, structOperandType));
364
+ }
365
+ else
366
+ {
367
+ assert(false && "gep type pair only support arr/ptr/struct");
368
+ }
369
+ }
370
+ return res; // Return the resulting byte offset as an IntervalValue.
201
371
  }
202
372
 
203
- void AbstractState::printTable(const VarToAbsValMap&table, std::ostream &oss) const
373
+ AbstractValue AbstractState::loadValue(NodeID varId)
204
374
  {
205
- oss.flags(std::ios::left);
206
- std::set<NodeID> ordered;
207
- for (const auto &item: table)
375
+ AbstractValue res;
376
+ for (auto addr : (*this)[varId].getAddrs())
208
377
  {
209
- ordered.insert(item.first);
378
+ res.join_with(load(addr)); // q = *p
210
379
  }
211
- for (const auto &item: ordered)
380
+ return res;
381
+ }
382
+ // storeValue
383
+ void AbstractState::storeValue(NodeID varId, AbstractValue val)
384
+ {
385
+ for (auto addr : (*this)[varId].getAddrs())
212
386
  {
213
- oss << "Var" << std::to_string(item);
214
- oss << "\t Value: " << table.at(item).toString() << "\n";
387
+ store(addr, val); // *p = q
215
388
  }
216
389
  }
390
+
391
+ void AbstractState::printAbstractState() const
392
+ {
393
+ SVFUtil::outs() << "-----------Var and Value-----------\n";
394
+ u32_t fieldWidth = 20;
395
+ SVFUtil::outs().flags(std::ios::left);
396
+ std::vector<std::pair<u32_t, AbstractValue>> varToAbsValVec(_varToAbsVal.begin(), _varToAbsVal.end());
397
+ std::sort(varToAbsValVec.begin(), varToAbsValVec.end(), [](const auto &a, const auto &b)
398
+ {
399
+ return a.first < b.first;
400
+ });
401
+ for (const auto &item: varToAbsValVec)
402
+ {
403
+ SVFUtil::outs() << std::left << std::setw(fieldWidth) << ("Var" + std::to_string(item.first));
404
+ if (item.second.isInterval())
405
+ {
406
+ SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
407
+ }
408
+ else if (item.second.isAddr())
409
+ {
410
+ SVFUtil::outs() << " Value: {";
411
+ u32_t i = 0;
412
+ for (const auto& addr: item.second.getAddrs())
413
+ {
414
+ ++i;
415
+ if (i < item.second.getAddrs().size())
416
+ {
417
+ SVFUtil::outs() << "0x" << std::hex << addr << ", ";
418
+ }
419
+ else
420
+ {
421
+ SVFUtil::outs() << "0x" << std::hex << addr;
422
+ }
423
+ }
424
+ SVFUtil::outs() << "}\n";
425
+ }
426
+ else
427
+ {
428
+ SVFUtil::outs() << " Value: ⊥\n";
429
+ }
430
+ }
431
+
432
+ std::vector<std::pair<u32_t, AbstractValue>> addrToAbsValVec(_addrToAbsVal.begin(), _addrToAbsVal.end());
433
+ std::sort(addrToAbsValVec.begin(), addrToAbsValVec.end(), [](const auto &a, const auto &b)
434
+ {
435
+ return a.first < b.first;
436
+ });
437
+
438
+ for (const auto& item: addrToAbsValVec)
439
+ {
440
+ std::ostringstream oss;
441
+ oss << "0x" << std::hex << AbstractState::getVirtualMemAddress(item.first);
442
+ SVFUtil::outs() << std::left << std::setw(fieldWidth) << oss.str();
443
+ if (item.second.isInterval())
444
+ {
445
+ SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
446
+ }
447
+ else if (item.second.isAddr())
448
+ {
449
+ SVFUtil::outs() << " Value: {";
450
+ u32_t i = 0;
451
+ for (const auto& addr: item.second.getAddrs())
452
+ {
453
+ ++i;
454
+ if (i < item.second.getAddrs().size())
455
+ {
456
+ SVFUtil::outs() << "0x" << std::hex << addr << ", ";
457
+ }
458
+ else
459
+ {
460
+ SVFUtil::outs() << "0x" << std::hex << addr;
461
+ }
462
+ }
463
+ SVFUtil::outs() << "}\n";
464
+ }
465
+ else
466
+ {
467
+ SVFUtil::outs() << " Value: ⊥\n";
468
+ }
469
+ }
470
+ SVFUtil::outs() << "-----------------------------------------\n";
471
+ }