svf-tools 1.0.938 → 1.0.940
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/AbstractValue.h +6 -287
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +6 -6
- package/svf/include/AE/Svfexe/BufOverflowChecker.h +1 -1
- package/svf/include/AE/Svfexe/SVFIR2AbsState.h +2 -2
- package/svf/include/Graphs/ConsGNode.h +9 -0
- package/svf/lib/AE/Core/RelationSolver.cpp +19 -16
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +22 -22
- package/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +21 -21
- package/svf/lib/AE/Svfexe/SVFIR2AbsState.cpp +12 -12
- package/svf/lib/Graphs/ConsG.cpp +5 -0
- package/svf-llvm/tools/AE/ae.cpp +12 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.940",
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
267
|
+
* @return IntervalValue of string length
|
|
268
268
|
*/
|
|
269
|
-
|
|
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
|
|
278
|
+
* @return IntervalValue of allocation size
|
|
279
279
|
*/
|
|
280
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
84
|
+
IntervalValue getByteOffset(const AbstractState& es, const GepStmt *gep);
|
|
85
85
|
|
|
86
86
|
/// Return the offset expression of a GepStmt
|
|
87
|
-
|
|
87
|
+
IntervalValue getElementIndex(const AbstractState& es, const GepStmt *gep);
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
static z3::context &getContext()
|
|
@@ -383,7 +383,16 @@ public:
|
|
|
383
383
|
}
|
|
384
384
|
//@}
|
|
385
385
|
|
|
386
|
+
virtual const std::string toString() const;
|
|
386
387
|
|
|
388
|
+
/// Overloading operator << for dumping node
|
|
389
|
+
//@{
|
|
390
|
+
friend OutStream &operator<<(OutStream &o, const ConstraintNode &node)
|
|
391
|
+
{
|
|
392
|
+
o << node.toString();
|
|
393
|
+
return o;
|
|
394
|
+
}
|
|
395
|
+
//@}
|
|
387
396
|
};
|
|
388
397
|
|
|
389
398
|
} // End namespace SVF
|
|
@@ -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
|
-
|
|
204
|
+
IntervalValue interval = item.second.getInterval();
|
|
205
|
+
if (interval.isBottom())
|
|
205
206
|
return Z3Expr::getContext().bool_val(false);
|
|
206
|
-
if (
|
|
207
|
+
if (interval.isTop())
|
|
207
208
|
continue;
|
|
208
209
|
Z3Expr v = toIntZ3Expr(item.first);
|
|
209
|
-
res = (res && v >= (int)
|
|
210
|
-
v <= (int)
|
|
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
|
-
|
|
285
|
-
|
|
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,
|
|
289
|
-
if (
|
|
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,
|
|
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, -
|
|
301
|
-
if (
|
|
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, -
|
|
305
|
-
if (
|
|
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, -
|
|
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
|
-
|
|
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
|
-
|
|
1218
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
1454
|
+
IntervalValue AbstractInterpretation::getStrlen(AbstractState& as, const SVF::SVFValue *strValue)
|
|
1455
1455
|
{
|
|
1456
|
-
|
|
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
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
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
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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),
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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)
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
636
|
-
|
|
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
|
-
|
|
696
|
-
|
|
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
|
-
|
|
1013
|
+
IntervalValue offsetPair = getElementIndex(es, gep);
|
|
1014
1014
|
if (!isVirtualMemAddress(*rhsVal.getAddrs().begin()))
|
|
1015
1015
|
return;
|
|
1016
1016
|
else
|
package/svf/lib/Graphs/ConsG.cpp
CHANGED
|
@@ -717,6 +717,11 @@ ConstraintNode::const_iterator ConstraintNode::directInEdgeEnd() const
|
|
|
717
717
|
}
|
|
718
718
|
//@}
|
|
719
719
|
|
|
720
|
+
const std::string ConstraintNode::toString() const
|
|
721
|
+
{
|
|
722
|
+
return SVFIR::getPAG()->getGNode(getId())->toString();
|
|
723
|
+
}
|
|
724
|
+
|
|
720
725
|
/*!
|
|
721
726
|
* GraphTraits specialization for constraint graph
|
|
722
727
|
*/
|
package/svf-llvm/tools/AE/ae.cpp
CHANGED
|
@@ -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);
|