svf-tools 1.0.938 → 1.0.939

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.938",
3
+ "version": "1.0.939",
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": {
@@ -168,317 +168,36 @@ public:
168
168
  AbstractValue(const IntervalValue& ival) : type(IntervalType), interval(ival) {}
169
169
 
170
170
  AbstractValue(const AddressValue& addr) : type(AddressType), addr(addr) {}
171
- // TODO: move constructor
171
+
172
172
  IntervalValue& getInterval()
173
173
  {
174
174
  if (isUnknown())
175
175
  {
176
176
  interval = IntervalValue::top();
177
177
  }
178
- assert(isInterval());
178
+ assert(isInterval() && "Attempting to retrieve an AbstractValue that is not an Interval!");
179
179
  return interval;
180
180
  }
181
181
 
182
- //
183
182
  const IntervalValue getInterval() const
184
183
  {
185
- assert(isInterval());
184
+ assert(isInterval() && "Attempting to retrieve an AbstractValue that is not an Interval!");
186
185
  return interval;
187
186
  }
188
187
 
189
188
  AddressValue& getAddrs()
190
189
  {
191
- assert(isAddr());
190
+ assert(isAddr() && "Attempting to retrieve an AbstractValue that is not an Address!");
192
191
  return addr;
193
192
  }
194
193
 
195
194
  const AddressValue getAddrs() const
196
195
  {
197
- assert(isAddr());
196
+ assert(isAddr() && "Attempting to retrieve an AbstractValue that is not an Address!");
198
197
  return addr;
199
198
  }
200
- ~AbstractValue() {};
201
-
202
-
203
- // interval visit funcs
204
- bool isTop() const
205
- {
206
- assert(isInterval());
207
- return interval.isTop();
208
- }
209
-
210
- bool isBottom() const
211
- {
212
- assert(isInterval());
213
- return interval.isBottom();
214
- }
215
-
216
- const BoundedInt& lb() const
217
- {
218
- assert(isInterval());
219
- return interval.lb();
220
- }
221
-
222
- const BoundedInt& ub() const
223
- {
224
- assert(isInterval());
225
- return interval.ub();
226
- }
227
-
228
- void setLb(const BoundedInt& lb)
229
- {
230
- assert(isInterval());
231
- interval.setLb(lb);
232
- }
233
-
234
- void setUb(const BoundedInt& ub)
235
- {
236
- assert(isInterval());
237
- interval.setUb(ub);
238
- }
239
-
240
- void setValue(const BoundedInt &lb, const BoundedInt &ub)
241
- {
242
- assert(isInterval());
243
- interval.setValue(lb, ub);
244
- }
245
-
246
- bool is_zero() const
247
- {
248
- assert(isInterval());
249
- return interval.is_zero();
250
- }
251
-
252
- bool is_infinite() const
253
- {
254
- assert(isInterval());
255
- return interval.is_infinite();
256
- }
257
-
258
- bool is_int() const
259
- {
260
- assert(isInterval());
261
- return interval.is_int();
262
- }
263
-
264
- bool is_real() const
265
- {
266
- assert(isInterval());
267
- return interval.is_real();
268
- }
269
-
270
- s64_t getIntNumeral() const
271
- {
272
- assert(isInterval());
273
- return interval.getIntNumeral();
274
- }
275
-
276
- double getRealNumeral() const
277
- {
278
- assert(isInterval());
279
- return interval.getRealNumeral();
280
- }
281
-
282
- bool is_numeral() const
283
- {
284
- assert(isInterval());
285
- return interval.is_numeral();
286
- }
287
-
288
- void set_to_bottom()
289
- {
290
- assert(isInterval());
291
- interval.set_to_bottom();
292
- }
293
-
294
- void set_to_top()
295
- {
296
- assert(isInterval());
297
- interval.set_to_top();
298
- }
299
199
 
300
- bool leq(const AbstractValue &other) const
301
- {
302
- assert(isInterval() && other.isInterval());
303
- return interval.leq(other.interval);
304
- }
305
-
306
- bool geq(const AbstractValue &other) const
307
- {
308
- assert(isInterval() && other.isInterval());
309
- return interval.geq(other.interval);
310
- }
311
-
312
- bool contains(s64_t n) const
313
- {
314
- assert(isInterval());
315
- return interval.contains(n);
316
- }
317
- // operator +-*/%>< >= <= << >> & | ^
318
- AbstractValue operator+(const AbstractValue &other) const
319
- {
320
- assert(isInterval() && other.isInterval());
321
- return interval + other.interval;
322
- }
323
- AbstractValue operator+(const IntervalValue &other) const
324
- {
325
- assert(isInterval());
326
- return interval + other;
327
- }
328
-
329
- AbstractValue operator-(const AbstractValue &other) const
330
- {
331
- assert(isInterval() && other.isInterval());
332
- return interval - other.interval;
333
- }
334
- AbstractValue operator-(const IntervalValue &other) const
335
- {
336
- assert(isInterval());
337
- return interval - other;
338
- }
339
-
340
- AbstractValue operator*(const AbstractValue &other) const
341
- {
342
- assert(isInterval() && other.isInterval());
343
- return interval * other.interval;
344
- }
345
- AbstractValue operator*(const IntervalValue &other) const
346
- {
347
- assert(isInterval());
348
- return interval * other;
349
- }
350
-
351
- AbstractValue operator/(const AbstractValue &other) const
352
- {
353
- assert(isInterval() && other.isInterval());
354
- return interval / other.interval;
355
- }
356
- AbstractValue operator/(const IntervalValue &other) const
357
- {
358
- assert(isInterval());
359
- return interval / other;
360
- }
361
-
362
- AbstractValue operator%(const AbstractValue &other) const
363
- {
364
- assert(isInterval() && other.isInterval());
365
- return interval % other.interval;
366
- }
367
- AbstractValue operator%(const IntervalValue &other) const
368
- {
369
- assert(isInterval());
370
- return interval % other;
371
- }
372
-
373
- AbstractValue operator>>(const AbstractValue &other) const
374
- {
375
- assert(isInterval() && other.isInterval());
376
- return interval >> other.interval;
377
- }
378
- AbstractValue operator>>(const IntervalValue &other) const
379
- {
380
- assert(isInterval());
381
- return interval >> other;
382
- }
383
-
384
- AbstractValue operator<<(const AbstractValue &other) const
385
- {
386
- assert(isInterval() && other.isInterval());
387
- return interval << other.interval;
388
- }
389
- AbstractValue operator<<(const IntervalValue &other) const
390
- {
391
- assert(isInterval());
392
- return interval << other;
393
- }
394
-
395
- AbstractValue operator&(const AbstractValue &other) const
396
- {
397
- assert(isInterval() && other.isInterval());
398
- return interval & other.interval;
399
- }
400
- AbstractValue operator&(const IntervalValue &other) const
401
- {
402
- assert(isInterval());
403
- return interval & other;
404
- }
405
-
406
- AbstractValue operator|(const AbstractValue &other) const
407
- {
408
- assert(isInterval() && other.isInterval());
409
- return interval | other.interval;
410
- }
411
- AbstractValue operator|(const IntervalValue &other) const
412
- {
413
- assert(isInterval());
414
- return interval | other;
415
- }
416
-
417
- AbstractValue operator^(const AbstractValue &other) const
418
- {
419
- assert(isInterval() && other.isInterval());
420
- return interval ^ other.interval;
421
- }
422
- AbstractValue operator^(const IntervalValue &other) const
423
- {
424
- assert(isInterval());
425
- return interval ^ other;
426
- }
427
-
428
- AbstractValue operator>(const AbstractValue &other) const
429
- {
430
- assert(isInterval() && other.isInterval());
431
- return interval > other.interval;
432
- }
433
- AbstractValue operator>(const IntervalValue &other) const
434
- {
435
- assert(isInterval());
436
- return interval > other;
437
- }
438
-
439
- AbstractValue operator<(const AbstractValue &other) const
440
- {
441
- assert(isInterval() && other.isInterval());
442
- return interval < other.interval;
443
- }
444
- AbstractValue operator<(const IntervalValue &other) const
445
- {
446
- assert(isInterval());
447
- return interval < other;
448
- }
449
-
450
- AbstractValue operator>=(const AbstractValue &other) const
451
- {
452
- assert(isInterval() && other.isInterval());
453
- return interval >= other.interval;
454
- }
455
- AbstractValue operator>=(const IntervalValue &other) const
456
- {
457
- assert(isInterval());
458
- return interval >= other;
459
- }
460
-
461
- AbstractValue operator<=(const AbstractValue &other) const
462
- {
463
- assert(isInterval() && other.isInterval());
464
- return interval <= other.interval;
465
- }
466
- AbstractValue operator<=(const IntervalValue &other) const
467
- {
468
- assert(isInterval());
469
- return interval <= other;
470
- }
471
-
472
-
473
- // address visit funcs
474
- std::pair<AddressValue::AddrSet::iterator, bool> insertAddr(u32_t id) // insertAddr
475
- {
476
- assert(isAddr());
477
- return addr.insert(id);
478
- }
479
-
480
- // TODO: equals, join_with, meet_with, widen_with, narrow_with, toString,
481
- // These should be merged with AddressValue
200
+ ~AbstractValue() {};
482
201
 
483
202
  bool equals(const AbstractValue &rhs) const
484
203
  {
@@ -264,9 +264,9 @@ protected:
264
264
  * e.g. source code str = "abc", return 3
265
265
  *
266
266
  * @param strValue SVFValue of string
267
- * @return AbstractValue of string length
267
+ * @return IntervalValue of string length
268
268
  */
269
- AbstractValue getStrlen(AbstractState& as, const SVF::SVFValue *strValue);
269
+ IntervalValue getStrlen(AbstractState& as, const SVF::SVFValue *strValue);
270
270
 
271
271
  /**
272
272
  * get memory allocation size
@@ -275,9 +275,9 @@ protected:
275
275
  * memset(arr, 1, 10* sizeof(int))
276
276
  * when we trace the 'arr', we can get the alloc size [40, 40]
277
277
  * @param value to be traced
278
- * @return AbstractValue of allocation size
278
+ * @return IntervalValue of allocation size
279
279
  */
280
- AbstractValue traceMemoryAllocationSize(AbstractState& as, const SVFValue *value);
280
+ IntervalValue traceMemoryAllocationSize(AbstractState& as, const SVFValue *value);
281
281
  /**
282
282
  * execute strcpy in abstract execution
283
283
  * e.g arr = new char[10]
@@ -304,7 +304,7 @@ protected:
304
304
  * we can set arr[3]='d', arr[4]='e', arr[5]='\0'
305
305
  * @param call callnode of memcpy like api
306
306
  */
307
- virtual void handleMemcpy(AbstractState& as, const SVFValue* dst, const SVFValue* src, AbstractValue len, u32_t start_idx);
307
+ virtual void handleMemcpy(AbstractState& as, const SVFValue* dst, const SVFValue* src, IntervalValue len, u32_t start_idx);
308
308
  /**
309
309
  * execute memset in abstract execution
310
310
  * e.g arr = new char[10]
@@ -312,7 +312,7 @@ protected:
312
312
  * we can set arr[0]='c', arr[1]='c', arr[2]='\0'
313
313
  * @param call callnode of memset like api
314
314
  */
315
- virtual void handleMemset(AbstractState& as, const SVFValue* dst, AbstractValue elem, AbstractValue len);
315
+ virtual void handleMemset(AbstractState& as, const SVFValue* dst, IntervalValue elem, IntervalValue len);
316
316
 
317
317
  /**
318
318
  * if this NodeID in SVFIR is a pointer, get the pointee type
@@ -164,7 +164,7 @@ protected:
164
164
  * @param len the length of the buffer overflow checkpoint
165
165
  * @return true if the buffer overflow is detected
166
166
  */
167
- bool canSafelyAccessMemory(const SVFValue *value, const AbstractValue &len, const ICFGNode *curNode);
167
+ bool canSafelyAccessMemory(const SVFValue *value, const IntervalValue &len, const ICFGNode *curNode);
168
168
 
169
169
  private:
170
170
  /**
@@ -81,10 +81,10 @@ public:
81
81
  /// e.g. GepStmt* gep = [i32*10], x, and x is [0,3]
82
82
  /// std::pair<s32_t, s32_t> byteOffset = getByteOffset(gep);
83
83
  /// byteOffset should be [0, 12] since i32 is 4 bytes.
84
- AbstractValue getByteOffset(const AbstractState& es, const GepStmt *gep);
84
+ IntervalValue getByteOffset(const AbstractState& es, const GepStmt *gep);
85
85
 
86
86
  /// Return the offset expression of a GepStmt
87
- AbstractValue getElementIndex(const AbstractState& es, const GepStmt *gep);
87
+ IntervalValue getElementIndex(const AbstractState& es, const GepStmt *gep);
88
88
 
89
89
 
90
90
  static z3::context &getContext()
@@ -201,13 +201,14 @@ Z3Expr RelationSolver::gamma_hat(const AbstractState& exeState) const
201
201
  Z3Expr res(Z3Expr::getContext().bool_val(true));
202
202
  for (auto& item : exeState.getVarToVal())
203
203
  {
204
- if (item.second.isBottom())
204
+ IntervalValue interval = item.second.getInterval();
205
+ if (interval.isBottom())
205
206
  return Z3Expr::getContext().bool_val(false);
206
- if (item.second.isTop())
207
+ if (interval.isTop())
207
208
  continue;
208
209
  Z3Expr v = toIntZ3Expr(item.first);
209
- res = (res && v >= (int)item.second.lb().getNumeral() &&
210
- v <= (int)item.second.ub().getNumeral()).simplify();
210
+ res = (res && v >= (int)interval.lb().getNumeral() &&
211
+ v <= (int)interval.ub().getNumeral()).simplify();
211
212
  }
212
213
  return res;
213
214
  }
@@ -236,8 +237,8 @@ Z3Expr RelationSolver::gamma_hat(u32_t id, const AbstractState& exeState) const
236
237
  assert(it != exeState.getVarToVal().end() && "id not in varToVal?");
237
238
  Z3Expr v = toIntZ3Expr(id);
238
239
  // Z3Expr v = Z3Expr::getContext().int_const(std::to_string(id).c_str());
239
- Z3Expr res = (v >= (int)it->second.lb().getNumeral() &&
240
- v <= (int)it->second.ub().getNumeral());
240
+ Z3Expr res = (v >= (int)it->second.getInterval().lb().getNumeral() &&
241
+ v <= (int)it->second.getInterval().ub().getNumeral());
241
242
  return res;
242
243
  }
243
244
 
@@ -281,31 +282,33 @@ AbstractState RelationSolver::BS(const AbstractState& domain, const Z3Expr &phi)
281
282
  /// init low, ret, high
282
283
  for (const auto& item: domain.getVarToVal())
283
284
  {
284
- updateMap(ret, item.first, item.second.ub().getFVal());
285
- if (item.second.lb().is_minus_infinity())
285
+ IntervalValue interval = item.second.getInterval();
286
+ updateMap(ret, item.first, interval.ub().getFVal());
287
+ if (interval.lb().is_minus_infinity())
286
288
  updateMap(low_values, item.first, -infinity);
287
289
  else
288
- updateMap(low_values, item.first, item.second.lb().getFVal());
289
- if (item.second.ub().is_plus_infinity())
290
+ updateMap(low_values, item.first, interval.lb().getFVal());
291
+ if (interval.ub().is_plus_infinity())
290
292
  updateMap(high_values, item.first, infinity);
291
293
  else
292
- updateMap(high_values, item.first, item.second.ub().getFVal());
294
+ updateMap(high_values, item.first, interval.ub().getFVal());
293
295
  if (item.first > bias)
294
296
  bias = item.first + 1;
295
297
  }
296
298
  for (const auto& item: domain.getVarToVal())
297
299
  {
298
300
  /// init objects -x
301
+ IntervalValue interval = item.second.getInterval();
299
302
  u32_t reverse_key = item.first + bias;
300
- updateMap(ret, reverse_key, -item.second.lb().getFVal());
301
- if (item.second.ub().is_plus_infinity())
303
+ updateMap(ret, reverse_key, -interval.lb().getFVal());
304
+ if (interval.ub().is_plus_infinity())
302
305
  updateMap(low_values, reverse_key, -infinity);
303
306
  else
304
- updateMap(low_values, reverse_key, -item.second.ub().getFVal());
305
- if (item.second.lb().is_minus_infinity())
307
+ updateMap(low_values, reverse_key, -interval.ub().getFVal());
308
+ if (interval.lb().is_minus_infinity())
306
309
  updateMap(high_values, reverse_key, infinity);
307
310
  else
308
- updateMap(high_values, reverse_key, -item.second.lb().getFVal());
311
+ updateMap(high_values, reverse_key, -interval.lb().getFVal());
309
312
  /// add a relation that x == -(x+bias)
310
313
  new_phi = (new_phi && (toIntZ3Expr(reverse_key) == -1 * toIntZ3Expr(item.first)));
311
314
  }
@@ -1153,11 +1153,11 @@ std::string AbstractInterpretation::strRead(AbstractState& as, const SVFValue* r
1153
1153
  }
1154
1154
  if (val.isUnknown())
1155
1155
  return str0;
1156
- if (!val.is_numeral())
1156
+ if (!val.getInterval().is_numeral())
1157
1157
  {
1158
1158
  break;
1159
1159
  }
1160
- if ((char) val.getIntNumeral() == '\0')
1160
+ if ((char) val.getInterval().getIntNumeral() == '\0')
1161
1161
  {
1162
1162
  break;
1163
1163
  }
@@ -1208,14 +1208,14 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
1208
1208
  // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
1209
1209
  else if (extType == MEMCPY)
1210
1210
  {
1211
- AbstractValue len = as[_svfir->getValueNode(cs.getArgument(2))];
1211
+ IntervalValue len = as[_svfir->getValueNode(cs.getArgument(2))].getInterval();
1212
1212
  handleMemcpy(as, cs.getArgument(0), cs.getArgument(1), len, 0);
1213
1213
  }
1214
1214
  else if (extType == MEMSET)
1215
1215
  {
1216
1216
  // memset dst is arg0, elem is arg1, size is arg2
1217
- AbstractValue len = as[_svfir->getValueNode(cs.getArgument(2))];
1218
- AbstractValue elem = as[_svfir->getValueNode(cs.getArgument(1))];
1217
+ IntervalValue len = as[_svfir->getValueNode(cs.getArgument(2))].getInterval();
1218
+ IntervalValue elem = as[_svfir->getValueNode(cs.getArgument(1))].getInterval();
1219
1219
  handleMemset(as,cs.getArgument(0), elem, len);
1220
1220
  }
1221
1221
  else if (extType == STRCPY)
@@ -1279,9 +1279,9 @@ void AbstractInterpretation::handleStrcpy(const CallICFGNode *call)
1279
1279
  CallSite cs = SVFUtil::getSVFCallSite(call->getCallSite());
1280
1280
  const SVFValue* arg0Val = cs.getArgument(0);
1281
1281
  const SVFValue* arg1Val = cs.getArgument(1);
1282
- AbstractValue strLen = getStrlen(as, arg1Val);
1282
+ IntervalValue strLen = getStrlen(as, arg1Val);
1283
1283
  // no need to -1, since it has \0 as the last byte
1284
- handleMemcpy(as, arg0Val, arg1Val, strLen,strLen.lb().getIntNumeral());
1284
+ handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
1285
1285
  }
1286
1286
 
1287
1287
  u32_t AbstractInterpretation::getAllocaInstByteSize(AbstractState& as, const AddrStmt *addr)
@@ -1307,8 +1307,8 @@ u32_t AbstractInterpretation::getAllocaInstByteSize(AbstractState& as, const Add
1307
1307
  {
1308
1308
  as[_svfir->getValueNode(value)] = IntervalValue(Options::MaxFieldLimit());
1309
1309
  }
1310
- AbstractValue itv =
1311
- as[_svfir->getValueNode(value)];
1310
+ IntervalValue itv =
1311
+ as[_svfir->getValueNode(value)].getInterval();
1312
1312
  res = res * itv.ub().getIntNumeral() > Options::MaxFieldLimit()? Options::MaxFieldLimit(): res * itv.ub().getIntNumeral();
1313
1313
  }
1314
1314
  return (u32_t)res;
@@ -1318,7 +1318,7 @@ u32_t AbstractInterpretation::getAllocaInstByteSize(AbstractState& as, const Add
1318
1318
  abort();
1319
1319
  }
1320
1320
 
1321
- AbstractValue AbstractInterpretation::traceMemoryAllocationSize(AbstractState& as, const SVFValue *value)
1321
+ IntervalValue AbstractInterpretation::traceMemoryAllocationSize(AbstractState& as, const SVFValue *value)
1322
1322
  {
1323
1323
  /// Usually called by a GepStmt overflow check, or external API (like memcpy) overflow check
1324
1324
  /// Defitions of Terms:
@@ -1400,7 +1400,7 @@ AbstractValue AbstractInterpretation::traceMemoryAllocationSize(AbstractState& a
1400
1400
  else
1401
1401
  {
1402
1402
  IntervalValue byteOffset =
1403
- _svfir2AbsState->getByteOffset(as, gep).getInterval();
1403
+ _svfir2AbsState->getByteOffset(as, gep);
1404
1404
  }
1405
1405
  // for variable offset, join with accumulate gep offset
1406
1406
  gep_offsets[gep->getICFGNode()] = byteOffset;
@@ -1451,9 +1451,9 @@ AbstractValue AbstractInterpretation::traceMemoryAllocationSize(AbstractState& a
1451
1451
  }
1452
1452
 
1453
1453
 
1454
- AbstractValue AbstractInterpretation::getStrlen(AbstractState& as, const SVF::SVFValue *strValue)
1454
+ IntervalValue AbstractInterpretation::getStrlen(AbstractState& as, const SVF::SVFValue *strValue)
1455
1455
  {
1456
- AbstractValue dst_size = traceMemoryAllocationSize(as, strValue);
1456
+ IntervalValue dst_size = traceMemoryAllocationSize(as, strValue);
1457
1457
  u32_t len = 0;
1458
1458
  NodeID dstid = _svfir->getValueNode(strValue);
1459
1459
  u32_t elemSize = 1;
@@ -1472,7 +1472,7 @@ AbstractValue AbstractInterpretation::getStrlen(AbstractState& as, const SVF::SV
1472
1472
  {
1473
1473
  return IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit());
1474
1474
  }
1475
- if (val.is_numeral() && (char) val.getIntNumeral() == '\0')
1475
+ if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
1476
1476
  {
1477
1477
  break;
1478
1478
  }
@@ -1522,9 +1522,9 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
1522
1522
  CallSite cs = SVFUtil::getSVFCallSite(call->getCallSite());
1523
1523
  const SVFValue* arg0Val = cs.getArgument(0);
1524
1524
  const SVFValue* arg1Val = cs.getArgument(1);
1525
- AbstractValue strLen0 = getStrlen(as, arg0Val);
1526
- AbstractValue strLen1 = getStrlen(as, arg1Val);
1527
- AbstractValue totalLen = strLen0 + strLen1;
1525
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
1526
+ IntervalValue strLen1 = getStrlen(as, arg1Val);
1527
+ IntervalValue totalLen = strLen0 + strLen1;
1528
1528
  handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
1529
1529
  // do memcpy
1530
1530
  }
@@ -1534,9 +1534,9 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
1534
1534
  const SVFValue* arg0Val = cs.getArgument(0);
1535
1535
  const SVFValue* arg1Val = cs.getArgument(1);
1536
1536
  const SVFValue* arg2Val = cs.getArgument(2);
1537
- AbstractValue arg2Num = as[_svfir->getValueNode(arg2Val)];
1538
- AbstractValue strLen0 = getStrlen(as, arg0Val);
1539
- AbstractValue totalLen = strLen0 + arg2Num;
1537
+ IntervalValue arg2Num = as[_svfir->getValueNode(arg2Val)].getInterval();
1538
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
1539
+ IntervalValue totalLen = strLen0 + arg2Num;
1540
1540
  handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
1541
1541
  // do memcpy
1542
1542
  }
@@ -1546,7 +1546,7 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
1546
1546
  }
1547
1547
  }
1548
1548
 
1549
- void AbstractInterpretation::handleMemcpy(AbstractState& as, const SVF::SVFValue *dst, const SVF::SVFValue *src, AbstractValue len, u32_t start_idx)
1549
+ void AbstractInterpretation::handleMemcpy(AbstractState& as, const SVF::SVFValue *dst, const SVF::SVFValue *src, IntervalValue len, u32_t start_idx)
1550
1550
  {
1551
1551
  u32_t dstId = _svfir->getValueNode(dst); // pts(dstId) = {objid} objbar objtypeinfo->getType().
1552
1552
  u32_t srcId = _svfir->getValueNode(src);
@@ -1625,7 +1625,7 @@ const SVFType* AbstractInterpretation::getPointeeElement(AbstractState& as, Node
1625
1625
  return nullptr;
1626
1626
  }
1627
1627
 
1628
- void AbstractInterpretation::handleMemset(AbstractState& as, const SVF::SVFValue *dst, AbstractValue elem, AbstractValue len)
1628
+ void AbstractInterpretation::handleMemset(AbstractState& as, const SVF::SVFValue *dst, IntervalValue elem, IntervalValue len)
1629
1629
  {
1630
1630
  u32_t dstId = _svfir->getValueNode(dst);
1631
1631
  u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
@@ -128,7 +128,7 @@ bool BufOverflowChecker::detectStrcpy(const CallICFGNode *call)
128
128
  CallSite cs = SVFUtil::getSVFCallSite(call->getCallSite());
129
129
  const SVFValue* arg0Val = cs.getArgument(0);
130
130
  const SVFValue* arg1Val = cs.getArgument(1);
131
- AbstractValue strLen = getStrlen(as, arg1Val);
131
+ IntervalValue strLen = getStrlen(as, arg1Val);
132
132
  // no need to -1, since it has \0 as the last byte
133
133
  return canSafelyAccessMemory(arg0Val, strLen, call);
134
134
  }
@@ -202,9 +202,9 @@ void BufOverflowChecker::initExtFunMap()
202
202
  AbstractState&as = getAbsState(callNode);
203
203
  u32_t block_count_id = _svfir->getValueNode(cs.getArgument(2));
204
204
  u32_t block_size_id = _svfir->getValueNode(cs.getArgument(1));
205
- AbstractValue block_count = as[block_count_id];
206
- AbstractValue block_size = as[block_size_id];
207
- AbstractValue block_byte = block_count * block_size;
205
+ IntervalValue block_count = as[block_count_id].getInterval();
206
+ IntervalValue block_size = as[block_size_id].getInterval();
207
+ IntervalValue block_byte = block_count * block_size;
208
208
  canSafelyAccessMemory(cs.getArgument(0), block_byte, _svfir->getICFG()->getICFGNode(cs.getInstruction()));
209
209
  };
210
210
  _func_map["fread"] = sse_fread;
@@ -236,7 +236,7 @@ void BufOverflowChecker::initExtFunMap()
236
236
  return;
237
237
  // assert(false && "we cannot support this type");
238
238
  }
239
- AbstractValue size = as[size_id] * IntervalValue(elemSize) - IntervalValue(1);
239
+ IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
240
240
  if (!as.inVarToAddrsTable(dst_id))
241
241
  {
242
242
  if (Options::BufferOverflowCheck())
@@ -273,7 +273,7 @@ void BufOverflowChecker::initExtFunMap()
273
273
 
274
274
  u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
275
275
  std::string snum = std::to_string(num);
276
- canSafelyAccessMemory(cs.getArgument(1), AbstractValue((s32_t)snum.size()), _svfir->getICFG()->getICFGNode(cs.getInstruction()));
276
+ canSafelyAccessMemory(cs.getArgument(1), IntervalValue((s32_t)snum.size()), _svfir->getICFG()->getICFGNode(cs.getInstruction()));
277
277
  };
278
278
  _func_map["itoa"] = sse_itoa;
279
279
 
@@ -285,7 +285,7 @@ void BufOverflowChecker::initExtFunMap()
285
285
  const SVFValue* strValue = cs.getArgument(0);
286
286
  const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(_svfir->getICFG()->getICFGNode(cs.getInstruction()));
287
287
  AbstractState& as = getAbsState(callNode);
288
- AbstractValue dst_size = getStrlen(as, strValue);
288
+ IntervalValue dst_size = getStrlen(as, strValue);
289
289
  u32_t elemSize = 1;
290
290
  if (strValue->getType()->isArrayTy())
291
291
  {
@@ -311,7 +311,7 @@ void BufOverflowChecker::initExtFunMap()
311
311
  const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(_svfir->getICFG()->getICFGNode(cs.getInstruction()));
312
312
  AbstractState&as = getAbsState(callNode);
313
313
  u32_t len_id = _svfir->getValueNode(cs.getArgument(2));
314
- AbstractValue len = as[len_id] - IntervalValue(1);
314
+ IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
315
315
  u32_t lhsId = _svfir->getValueNode(cs.getInstruction());
316
316
  as[lhsId] = len;
317
317
  canSafelyAccessMemory(cs.getArgument(1), len, _svfir->getICFG()->getICFGNode(cs.getInstruction()));;
@@ -326,7 +326,7 @@ void BufOverflowChecker::initExtFunMap()
326
326
  if (cs.arg_size() < 2) return;
327
327
  AbstractState&as = getAbsState(callNode);
328
328
  u32_t size_id = _svfir->getValueNode(cs.getArgument(1));
329
- AbstractValue val = as[size_id];
329
+ IntervalValue val = as[size_id].getInterval();
330
330
  if (val.isBottom())
331
331
  {
332
332
  val = IntervalValue(0);
@@ -356,7 +356,7 @@ void BufOverflowChecker::initExtFunMap()
356
356
  if (cs.arg_size() < 2) return;
357
357
  AbstractState&as = getAbsState(callNode);
358
358
  u32_t size_id = _svfir->getValueNode(cs.getArgument(1));
359
- AbstractValue val = as[size_id];
359
+ IntervalValue val = as[size_id].getInterval();
360
360
  if (val.isBottom())
361
361
  {
362
362
  assert(false && "UNSAFE_BUFACCESS size is bottom");
@@ -400,9 +400,9 @@ bool BufOverflowChecker::detectStrcat(const CallICFGNode *call)
400
400
  CallSite cs = SVFUtil::getSVFCallSite(call->getCallSite());
401
401
  const SVFValue* arg0Val = cs.getArgument(0);
402
402
  const SVFValue* arg1Val = cs.getArgument(1);
403
- AbstractValue strLen0 = getStrlen(as, arg0Val);
404
- AbstractValue strLen1 = getStrlen(as, arg1Val);
405
- AbstractValue totalLen = strLen0 + strLen1;
403
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
404
+ IntervalValue strLen1 = getStrlen(as, arg1Val);
405
+ IntervalValue totalLen = strLen0 + strLen1;
406
406
  return canSafelyAccessMemory(arg0Val, totalLen, call);
407
407
  }
408
408
  else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
@@ -410,9 +410,9 @@ bool BufOverflowChecker::detectStrcat(const CallICFGNode *call)
410
410
  CallSite cs = SVFUtil::getSVFCallSite(call->getCallSite());
411
411
  const SVFValue* arg0Val = cs.getArgument(0);
412
412
  const SVFValue* arg2Val = cs.getArgument(2);
413
- AbstractValue arg2Num = as[_svfir->getValueNode(arg2Val)];
414
- AbstractValue strLen0 = getStrlen(as, arg0Val);
415
- AbstractValue totalLen = strLen0 + arg2Num;
413
+ IntervalValue arg2Num = as[_svfir->getValueNode(arg2Val)].getInterval();
414
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
415
+ IntervalValue totalLen = strLen0 + arg2Num;
416
416
  return canSafelyAccessMemory(arg0Val, totalLen, call);
417
417
  }
418
418
  else
@@ -462,7 +462,7 @@ void BufOverflowChecker::handleExtAPI(const CallICFGNode *call)
462
462
  // loop the args and check the offset
463
463
  for (auto arg: args)
464
464
  {
465
- AbstractValue offset = as[_svfir->getValueNode(cs.getArgument(arg.second))] - IntervalValue(1);
465
+ IntervalValue offset = as[_svfir->getValueNode(cs.getArgument(arg.second))].getInterval() - IntervalValue(1);
466
466
  canSafelyAccessMemory(cs.getArgument(arg.first), offset, call);
467
467
  }
468
468
  }
@@ -479,7 +479,7 @@ void BufOverflowChecker::handleExtAPI(const CallICFGNode *call)
479
479
  // loop the args and check the offset
480
480
  for (auto arg: args)
481
481
  {
482
- AbstractValue offset = as[_svfir->getValueNode(cs.getArgument(arg.second))] - IntervalValue(1);
482
+ IntervalValue offset = as[_svfir->getValueNode(cs.getArgument(arg.second))].getInterval() - IntervalValue(1);
483
483
  canSafelyAccessMemory(cs.getArgument(arg.first), offset, call);
484
484
  }
485
485
  }
@@ -498,7 +498,7 @@ void BufOverflowChecker::handleExtAPI(const CallICFGNode *call)
498
498
  return;
499
499
  }
500
500
 
501
- bool BufOverflowChecker::canSafelyAccessMemory(const SVFValue *value, const AbstractValue &len, const ICFGNode *curNode)
501
+ bool BufOverflowChecker::canSafelyAccessMemory(const SVFValue *value, const IntervalValue &len, const ICFGNode *curNode)
502
502
  {
503
503
  AbstractState& as = getAbsState(curNode);
504
504
  const SVFValue *firstValue = value;
@@ -514,7 +514,7 @@ bool BufOverflowChecker::canSafelyAccessMemory(const SVFValue *value, const Abst
514
514
  Set<const SVFValue *> visited;
515
515
  visited.insert(value);
516
516
  Map<const ICFGNode *, IntervalValue> gep_offsets;
517
- IntervalValue total_bytes = len.getInterval();
517
+ IntervalValue total_bytes = len;
518
518
  worklist.push(value);
519
519
  std::vector<const CallICFGNode *> callstack = _callSiteStack;
520
520
  while (!worklist.empty())
@@ -569,7 +569,7 @@ bool BufOverflowChecker::canSafelyAccessMemory(const SVFValue *value, const Abst
569
569
  else
570
570
  {
571
571
  byteOffset =
572
- _svfir2AbsState->getByteOffset(as, gep).getInterval();
572
+ _svfir2AbsState->getByteOffset(as, gep);
573
573
  }
574
574
  // for variable offset, join with accumulate gep offset
575
575
  gep_offsets[gep->getICFGNode()] = byteOffset;
@@ -361,19 +361,19 @@ AbstractValue SVFIR2AbsState::getGepObjAddress(AbstractState& es, u32_t pointer,
361
361
  {
362
362
  assert(!getAddrs(es, pointer).getAddrs().empty());
363
363
  AbstractValue addrs = getAddrs(es, pointer);
364
- AbstractValue ret = AddressValue();
364
+ AddressValue ret = AddressValue();
365
365
  for (const auto &addr: addrs.getAddrs())
366
366
  {
367
367
  s64_t baseObj = getInternalID(addr);
368
368
  if (baseObj == 0)
369
369
  {
370
- ret.insertAddr(getVirtualMemAddress(0));
370
+ ret.insert(getVirtualMemAddress(0));
371
371
  continue;
372
372
  }
373
373
  assert(SVFUtil::isa<ObjVar>(_svfir->getGNode(baseObj)) && "Fail to get the base object address!");
374
374
  NodeID gepObj = _svfir->getGepObjVar(baseObj, offset);
375
375
  initSVFVar(es, gepObj);
376
- ret.insertAddr(getVirtualMemAddress(gepObj));
376
+ ret.insert(getVirtualMemAddress(gepObj));
377
377
  }
378
378
  return ret;
379
379
  }
@@ -400,11 +400,11 @@ AbstractValue SVFIR2AbsState::getGepObjAddress(AbstractState& es, u32_t pointer,
400
400
  * Therefore the final byteoffset is [8+4*var1.lb(), 8+4*var1.ub()]
401
401
  *
402
402
  */
403
- AbstractValue SVFIR2AbsState::getByteOffset(const AbstractState& es, const GepStmt *gep)
403
+ IntervalValue SVFIR2AbsState::getByteOffset(const AbstractState& es, const GepStmt *gep)
404
404
  {
405
405
  if (gep->isConstantOffset())
406
406
  return IntervalValue((s64_t)gep->accumulateConstantByteOffset());
407
- AbstractValue res = IntervalValue(0); // Initialize the result interval 'res' to 0.
407
+ IntervalValue res = IntervalValue(0); // Initialize the result interval 'res' to 0.
408
408
  // Loop through the offsetVarAndGepTypePairVec in reverse order.
409
409
  for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
410
410
  {
@@ -470,11 +470,11 @@ AbstractValue SVFIR2AbsState::getByteOffset(const AbstractState& es, const GepSt
470
470
  *
471
471
  * @return A pair of APOffset values representing the offset range.
472
472
  */
473
- AbstractValue SVFIR2AbsState::getElementIndex(const AbstractState& es, const GepStmt *gep)
473
+ IntervalValue SVFIR2AbsState::getElementIndex(const AbstractState& es, const GepStmt *gep)
474
474
  {
475
475
  if (gep->isConstantOffset())
476
476
  return IntervalValue((s64_t)gep->accumulateConstantOffset());
477
- AbstractValue res = IntervalValue(0);
477
+ IntervalValue res = IntervalValue(0);
478
478
  for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
479
479
  {
480
480
  AccessPath::IdxOperandPair IdxVarAndType =
@@ -632,8 +632,8 @@ void SVFIR2AbsState::handleBinary(AbstractState& es, const BinaryOPStmt *binary)
632
632
  if (!inVarToValTable(es, op1)) es[op1] = IntervalValue::top();
633
633
  if (inVarToValTable(es, op0) && inVarToValTable(es, op1))
634
634
  {
635
- AbstractValue &lhs = es[op0], &rhs = es[op1];
636
- AbstractValue resVal;
635
+ IntervalValue &lhs = es[op0].getInterval(), &rhs = es[op1].getInterval();
636
+ IntervalValue resVal;
637
637
  switch (binary->getOpcode())
638
638
  {
639
639
  case BinaryOPStmt::Add:
@@ -692,8 +692,8 @@ void SVFIR2AbsState::handleCmp(AbstractState& es, const CmpStmt *cmp)
692
692
  u32_t res = cmp->getResID();
693
693
  if (inVarToValTable(es, op0) && inVarToValTable(es, op1))
694
694
  {
695
- AbstractValue resVal;
696
- AbstractValue &lhs = es[op0], &rhs = es[op1];
695
+ IntervalValue resVal;
696
+ IntervalValue &lhs = es[op0].getInterval(), &rhs = es[op1].getInterval();
697
697
  //AbstractValue
698
698
  auto predicate = cmp->getPredicate();
699
699
  switch (predicate)
@@ -1010,7 +1010,7 @@ void SVFIR2AbsState::handleGep(AbstractState& es, const GepStmt *gep)
1010
1010
  if (!inVarToAddrsTable(es, rhs)) return;
1011
1011
  AbstractValue &rhsVal = es[rhs];
1012
1012
  assert(!rhsVal.getAddrs().empty());
1013
- AbstractValue offsetPair = getElementIndex(es, gep);
1013
+ IntervalValue offsetPair = getElementIndex(es, gep);
1014
1014
  if (!isVirtualMemAddress(*rhsVal.getAddrs().begin()))
1015
1015
  return;
1016
1016
  else
@@ -111,7 +111,7 @@ public:
111
111
  // var1 := var0 + 1;
112
112
  relation[1] =
113
113
  getContext().int_const("1") == getContext().int_const("0") + 1;
114
- itv[1] = itv[0] + IntervalValue(1);
114
+ itv[1] = itv[0].getInterval() + IntervalValue(1);
115
115
  // Test extract sub vars
116
116
  Set<u32_t> res;
117
117
  relation.extractSubVars(relation[1], res);
@@ -145,7 +145,7 @@ public:
145
145
  // var1 := var0 + 1;
146
146
  relation[1] =
147
147
  getContext().int_const("1") == getContext().int_const("0") * 2;
148
- itv[1] = itv[0] * IntervalValue(2);
148
+ itv[1] = itv[0].getInterval() * IntervalValue(2);
149
149
 
150
150
  // Test extract sub vars
151
151
  Set<u32_t> res;
@@ -184,7 +184,7 @@ public:
184
184
  // var2 := var1 - var0;
185
185
  relation[2] = getContext().int_const("2") ==
186
186
  getContext().int_const("1") - getContext().int_const("0");
187
- itv[2] = itv[1] - itv[0];
187
+ itv[2] = itv[1].getInterval() - itv[0].getInterval();
188
188
  // Test extract sub vars
189
189
  Set<u32_t> res;
190
190
  relation.extractSubVars(relation[2], res);
@@ -226,7 +226,7 @@ public:
226
226
  // var2 := var1 - var0;
227
227
  relation[2] = getContext().int_const("2") ==
228
228
  getContext().int_const("1") - getContext().int_const("0");
229
- itv[2] = itv[1] - itv[0];
229
+ itv[2] = itv[1].getInterval() - itv[0].getInterval();
230
230
 
231
231
  // Test extract sub vars
232
232
  Set<u32_t> res;
@@ -269,7 +269,7 @@ public:
269
269
  // var2 := var1 - var0;
270
270
  relation[2] = getContext().int_const("2") ==
271
271
  getContext().int_const("1") - getContext().int_const("0");
272
- itv[2] = itv[1] - itv[0];
272
+ itv[2] = itv[1].getInterval() - itv[0].getInterval();
273
273
 
274
274
  // Test extract sub vars
275
275
  Set<u32_t> res;
@@ -312,7 +312,7 @@ public:
312
312
  // var2 := var1 - var0;
313
313
  relation[2] = getContext().int_const("2") ==
314
314
  getContext().int_const("1") - getContext().int_const("0");
315
- itv[2] = itv[1] - itv[0];
315
+ itv[2] = itv[1].getInterval() - itv[0].getInterval();
316
316
 
317
317
  // Test extract sub vars
318
318
  Set<u32_t> res;
@@ -355,7 +355,7 @@ public:
355
355
  // var2 := var1 - var0;
356
356
  relation[2] = getContext().int_const("2") ==
357
357
  getContext().int_const("1") - getContext().int_const("0");
358
- itv[2] = itv[1] - itv[0];
358
+ itv[2] = itv[1].getInterval() - itv[0].getInterval();
359
359
 
360
360
  // Test extract sub vars
361
361
  Set<u32_t> res;
@@ -398,7 +398,7 @@ public:
398
398
  // var2 := var1 / var0;
399
399
  relation[2] = getContext().int_const("2") ==
400
400
  getContext().int_const("1") / getContext().int_const("0");
401
- itv[2] = itv[1] / itv[0];
401
+ itv[2] = itv[1].getInterval() / itv[0].getInterval();
402
402
  // Test extract sub vars
403
403
  Set<u32_t> res;
404
404
  relation.extractSubVars(relation[2], res);
@@ -440,7 +440,7 @@ public:
440
440
  // var2 := var1 / var0;
441
441
  relation[2] = getContext().int_const("2") ==
442
442
  getContext().int_const("1") / getContext().int_const("0");
443
- itv[2] = itv[1] / itv[0];
443
+ itv[2] = itv[1].getInterval() / itv[0].getInterval();
444
444
  // Test extract sub vars
445
445
  Set<u32_t> res;
446
446
  relation.extractSubVars(relation[2], res);
@@ -482,7 +482,7 @@ public:
482
482
  // var2 := var1 / var0;
483
483
  relation[2] = getContext().int_const("2") ==
484
484
  getContext().int_const("1") / getContext().int_const("0");
485
- itv[2] = itv[1] / itv[0];
485
+ itv[2] = itv[1].getInterval() / itv[0].getInterval();
486
486
  // Test extract sub vars
487
487
  Set<u32_t> res;
488
488
  relation.extractSubVars(relation[2], res);
@@ -523,7 +523,7 @@ public:
523
523
  // var2 := var1 / var0;
524
524
  relation[2] = getContext().int_const("2") ==
525
525
  getContext().int_const("1") / getContext().int_const("0");
526
- itv[2] = itv[1] / itv[0];
526
+ itv[2] = itv[1].getInterval() / itv[0].getInterval();
527
527
  // Test extract sub vars
528
528
  Set<u32_t> res;
529
529
  relation.extractSubVars(relation[2], res);
@@ -565,7 +565,7 @@ public:
565
565
  // var2 := var1 / var0;
566
566
  relation[2] = getContext().int_const("2") ==
567
567
  getContext().int_const("1") / getContext().int_const("0");
568
- itv[2] = itv[1] / itv[0];
568
+ itv[2] = itv[1].getInterval() / itv[0].getInterval();
569
569
  // Test extract sub vars
570
570
  Set<u32_t> res;
571
571
  relation.extractSubVars(relation[2], res);