svf-lib 1.0.1925 → 1.0.1926

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.
@@ -0,0 +1,750 @@
1
+ //===- AbstractExeState.h ----Interval Domain-------------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2022> <Yulei Sui>
6
+ //
7
+
8
+ // This program is free software: you can redistribute it and/or modify
9
+ // it under the terms of the GNU Affero General Public License as published by
10
+ // the Free Software Foundation, either version 3 of the License, or
11
+ // (at your option) any later version.
12
+
13
+ // This program is distributed in the hope that it will be useful,
14
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ // GNU Affero General Public License for more details.
17
+
18
+ // You should have received a copy of the GNU Affero General Public License
19
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ //
21
+ //===----------------------------------------------------------------------===//
22
+ /*
23
+ * IntervalExeState.h
24
+ *
25
+ * Created on: Jul 9, 2022
26
+ * Author: Xiao Cheng, Jiawei Wang
27
+ *
28
+ * [-oo,+oo]
29
+ * / / \ \
30
+ * [-oo,1] ... [-oo,10] ... [-1,+oo] ... [0,+oo]
31
+ * \ \ / /
32
+ * \ [-1,10] /
33
+ * \ / \ /
34
+ * ... [-1,1] ... [0,10] ...
35
+ * \ | \ / \ /
36
+ * ... [-1,0] [0,1] ... [1,9] ...
37
+ * \ | \ | \ /
38
+ * ... [-1,-1] [0,0] [1,1] ...
39
+ * \ \ \ / /
40
+ * ⊥
41
+ */
42
+
43
+ #ifndef Z3_EXAMPLE_INTERVAL_DOMAIN_H
44
+ #define Z3_EXAMPLE_INTERVAL_DOMAIN_H
45
+
46
+ #include "AE/Core/ExeState.h"
47
+ #include "AE/Core/IntervalValue.h"
48
+ #include "AE/Core/AbstractValue.h"
49
+ #include "Util/Z3Expr.h"
50
+
51
+ #include <iomanip>
52
+
53
+ namespace SVF
54
+ {
55
+ class AbstractState
56
+ {
57
+ friend class SVFIR2ItvExeState;
58
+ friend class RelationSolver;
59
+ public:
60
+ typedef Map<u32_t, AbstractValue> VarToAbsValMap;
61
+
62
+ typedef VarToAbsValMap LocToAbsValMap;
63
+
64
+ public:
65
+ /// default constructor
66
+ AbstractState() {}
67
+
68
+ AbstractState(VarToAbsValMap&_varToValMap, LocToAbsValMap&_locToValMap) : _varToAbsVal(_varToValMap),
69
+ _locToAbsVal(_locToValMap) {}
70
+
71
+ /// copy constructor
72
+ AbstractState(const AbstractState&rhs) : _varToAbsVal(rhs.getVarToVal()),
73
+ _locToAbsVal(rhs.getLocToVal())
74
+ {
75
+
76
+ }
77
+
78
+ virtual ~AbstractState() = default;
79
+
80
+
81
+ /// The physical address starts with 0x7f...... + idx
82
+ static inline u32_t getVirtualMemAddress(u32_t idx)
83
+ {
84
+ return AddressValue::getVirtualMemAddress(idx);
85
+ }
86
+
87
+ /// Check bit value of val start with 0x7F000000, filter by 0xFF000000
88
+ static inline bool isVirtualMemAddress(u32_t val)
89
+ {
90
+ return AddressValue::isVirtualMemAddress(val);
91
+ }
92
+
93
+ /// Return the internal index if idx is an address otherwise return the value of idx
94
+ static inline u32_t getInternalID(u32_t idx)
95
+ {
96
+ return AddressValue::getInternalID(idx);
97
+ }
98
+
99
+ static inline bool isNullPtr(u32_t addr)
100
+ {
101
+ return getInternalID(addr) == 0;
102
+ }
103
+
104
+ AbstractState&operator=(const AbstractState&rhs)
105
+ {
106
+ if (rhs != *this)
107
+ {
108
+ _varToAbsVal = rhs._varToAbsVal;
109
+ _locToAbsVal = rhs._locToAbsVal;
110
+ }
111
+ return *this;
112
+ }
113
+
114
+ /// move constructor
115
+ AbstractState(AbstractState&&rhs) : _varToAbsVal(std::move(rhs._varToAbsVal)),
116
+ _locToAbsVal(std::move(rhs._locToAbsVal))
117
+ {
118
+
119
+ }
120
+
121
+ /// operator= move constructor
122
+ AbstractState&operator=(AbstractState&&rhs)
123
+ {
124
+ if (&rhs != this)
125
+ {
126
+ _varToAbsVal = std::move(rhs._varToAbsVal);
127
+ _locToAbsVal = std::move(rhs._locToAbsVal);
128
+ }
129
+ return *this;
130
+ }
131
+
132
+ /// Set all value bottom
133
+ AbstractState bottom() const
134
+ {
135
+ AbstractState inv = *this;
136
+ for (auto &item: inv._varToAbsVal)
137
+ {
138
+ if (item.second.isInterval())
139
+ item.second.getInterval().set_to_bottom();
140
+ }
141
+ return inv;
142
+ }
143
+
144
+ /// Set all value top
145
+ AbstractState top() const
146
+ {
147
+ AbstractState inv = *this;
148
+ for (auto &item: inv._varToAbsVal)
149
+ {
150
+ if (item.second.isInterval())
151
+ item.second.getInterval().set_to_top();
152
+ }
153
+ return inv;
154
+ }
155
+
156
+ /// Copy some values and return a new IntervalExeState
157
+ AbstractState sliceState(Set<u32_t> &sl)
158
+ {
159
+ AbstractState inv;
160
+ for (u32_t id: sl)
161
+ {
162
+ inv._varToAbsVal[id] = _varToAbsVal[id];
163
+ }
164
+ return inv;
165
+ }
166
+
167
+ protected:
168
+ VarToAbsValMap _varToAbsVal; ///< Map a variable (symbol) to its abstract value
169
+ LocToAbsValMap _locToAbsVal; ///< Map a memory address to its stored abstract value
170
+
171
+ public:
172
+
173
+
174
+ /// get abstract value of variable
175
+ inline virtual AbstractValue &operator[](u32_t varId)
176
+ {
177
+ return _varToAbsVal[varId];
178
+ }
179
+
180
+ /// get abstract value of variable
181
+ inline virtual const AbstractValue &operator[](u32_t varId) const
182
+ {
183
+ return _varToAbsVal.at(varId);
184
+ }
185
+
186
+ /// whether the variable is in varToAddrs table
187
+ inline bool inVarToAddrsTable(u32_t id) const
188
+ {
189
+ if (_varToAbsVal.find(id)!= _varToAbsVal.end())
190
+ {
191
+ if (_varToAbsVal.at(id).isAddr())
192
+ {
193
+ return true;
194
+ }
195
+ }
196
+ return false;
197
+ }
198
+
199
+ /// whether the variable is in varToVal table
200
+ inline virtual bool inVarToValTable(u32_t id) const
201
+ {
202
+ if (_varToAbsVal.find(id) != _varToAbsVal.end())
203
+ {
204
+ if (_varToAbsVal.at(id).isInterval())
205
+ {
206
+ return true;
207
+ }
208
+ }
209
+ return false;
210
+ }
211
+
212
+ /// whether the memory address stores memory addresses
213
+ inline bool inLocToAddrsTable(u32_t id) const
214
+ {
215
+ if (_locToAbsVal.find(id)!= _locToAbsVal.end())
216
+ {
217
+ if (_locToAbsVal.at(id).isAddr())
218
+ {
219
+ return true;
220
+ }
221
+ }
222
+ return false;
223
+ }
224
+
225
+ /// whether the memory address stores abstract value
226
+ inline virtual bool inLocToValTable(u32_t id) const
227
+ {
228
+ if (_locToAbsVal.find(id) != _locToAbsVal.end())
229
+ {
230
+ if (_locToAbsVal.at(id).isInterval())
231
+ {
232
+ return true;
233
+ }
234
+ }
235
+ return false;
236
+ }
237
+
238
+ /// get var2val map
239
+ const VarToAbsValMap&getVarToVal() const
240
+ {
241
+ return _varToAbsVal;
242
+ }
243
+
244
+ /// get loc2val map
245
+ const LocToAbsValMap&getLocToVal() const
246
+ {
247
+ return _locToAbsVal;
248
+ }
249
+
250
+ public:
251
+
252
+ /// domain widen with other, and return the widened domain
253
+ AbstractState widening(const AbstractState&other);
254
+
255
+ /// domain narrow with other, and return the narrowed domain
256
+ AbstractState narrowing(const AbstractState&other);
257
+
258
+ /// domain widen with other, important! other widen this.
259
+ void widenWith(const AbstractState&other);
260
+
261
+ /// domain join with other, important! other widen this.
262
+ void joinWith(const AbstractState&other);
263
+
264
+ /// domain narrow with other, important! other widen this.
265
+ void narrowWith(const AbstractState&other);
266
+
267
+ /// domain meet with other, important! other widen this.
268
+ void meetWith(const AbstractState&other);
269
+
270
+
271
+ /// Return int value from an expression if it is a numeral, otherwise return an approximate value
272
+ inline s32_t Interval2NumValue(const IntervalValue &e) const
273
+ {
274
+ //TODO: return concrete value;
275
+ return (s32_t) e.lb().getNumeral();
276
+ }
277
+
278
+ /// Return true if map has bottom value
279
+ inline bool has_bottom()
280
+ {
281
+ for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
282
+ {
283
+ if (it->second.isInterval())
284
+ {
285
+ if (it->second.getInterval().isBottom())
286
+ {
287
+ return true;
288
+ }
289
+ }
290
+ }
291
+ for (auto it = _locToAbsVal.begin(); it != _locToAbsVal.end(); ++it)
292
+ {
293
+ if (it->second.isInterval())
294
+ {
295
+ if (it->second.getInterval().isBottom())
296
+ {
297
+ return true;
298
+ }
299
+ }
300
+ }
301
+ return false;
302
+ }
303
+
304
+ u32_t hash() const;
305
+
306
+ public:
307
+ inline void store(u32_t addr, const AbstractValue &val)
308
+ {
309
+ assert(isVirtualMemAddress(addr) && "not virtual address?");
310
+ if (isNullPtr(addr)) return;
311
+ u32_t objId = getInternalID(addr);
312
+ _locToAbsVal[objId] = val;
313
+ }
314
+
315
+ inline virtual AbstractValue &load(u32_t addr)
316
+ {
317
+ assert(isVirtualMemAddress(addr) && "not virtual address?");
318
+ u32_t objId = getInternalID(addr);
319
+ auto it = _locToAbsVal.find(objId);
320
+ if(it != _locToAbsVal.end())
321
+ return it->second;
322
+ else
323
+ {
324
+ _locToAbsVal[objId] = IntervalValue::top();
325
+ return _locToAbsVal[objId];
326
+ }
327
+ }
328
+
329
+
330
+ /// Print values of all expressions
331
+ void printExprValues(std::ostream &oss) const;
332
+
333
+ std::string toString() const
334
+ {
335
+ return "";
336
+ }
337
+
338
+ bool equals(const AbstractState&other) const;
339
+
340
+ static bool eqVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
341
+ {
342
+ if (lhs.size() != rhs.size()) return false;
343
+ for (const auto &item: lhs)
344
+ {
345
+ auto it = rhs.find(item.first);
346
+ if (it == rhs.end())
347
+ return false;
348
+ if (item.second.getType() == it->second.getType())
349
+ {
350
+ if (item.second.isInterval())
351
+ {
352
+ if (!item.second.getInterval().equals(it->second.getInterval()))
353
+ {
354
+ return false;
355
+ }
356
+ }
357
+ else if (item.second.isAddr())
358
+ {
359
+ if (!item.second.getAddrs().equals(it->second.getAddrs()))
360
+ {
361
+ return false;
362
+ }
363
+ }
364
+ }
365
+ else
366
+ {
367
+ return false;
368
+ }
369
+ }
370
+ return true;
371
+ }
372
+
373
+
374
+ static bool lessThanVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
375
+ {
376
+ if (lhs.empty()) return !rhs.empty();
377
+ for (const auto &item: lhs)
378
+ {
379
+ auto it = rhs.find(item.first);
380
+ if (it == rhs.end()) return false;
381
+ // judge from expr id
382
+ if (item.second.getInterval().geq(it->second.getInterval())) return false;
383
+ }
384
+ return true;
385
+ }
386
+
387
+ // lhs >= rhs
388
+ static bool geqVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
389
+ {
390
+ if (rhs.empty()) return true;
391
+ for (const auto &item: rhs)
392
+ {
393
+ auto it = lhs.find(item.first);
394
+ if (it == lhs.end()) return false;
395
+ // judge from expr id
396
+ if (it->second.isInterval() && item.second.isInterval())
397
+ {
398
+ if (!it->second.getInterval().geq(item.second.getInterval()))
399
+ return false;
400
+ }
401
+
402
+ }
403
+ return true;
404
+ }
405
+
406
+ bool operator==(const AbstractState&rhs) const
407
+ {
408
+ return eqVarToValMap(_varToAbsVal, rhs.getVarToVal()) &&
409
+ eqVarToValMap(_locToAbsVal, rhs.getLocToVal());
410
+ }
411
+
412
+ bool operator!=(const AbstractState&rhs) const
413
+ {
414
+ return !(*this == rhs);
415
+ }
416
+
417
+ bool operator<(const AbstractState&rhs) const
418
+ {
419
+ return !(*this >= rhs);
420
+ }
421
+
422
+
423
+ bool operator>=(const AbstractState&rhs) const
424
+ {
425
+ return geqVarToValMap(_varToAbsVal, rhs.getVarToVal()) && geqVarToValMap(_locToAbsVal, rhs.getLocToVal());
426
+ }
427
+
428
+ void clear()
429
+ {
430
+ _locToAbsVal.clear();
431
+ _varToAbsVal.clear();
432
+ }
433
+
434
+
435
+ protected:
436
+ void printTable(const VarToAbsValMap&table, std::ostream &oss) const;
437
+
438
+ };
439
+
440
+ class SparseAbstractState : public AbstractState
441
+ {
442
+ friend class SVFIR2ItvExeState;
443
+ friend class RelationSolver;
444
+
445
+ public:
446
+ static SparseAbstractState globalES;
447
+
448
+ public:
449
+ /// default constructor
450
+ SparseAbstractState() : AbstractState() {}
451
+
452
+ SparseAbstractState(VarToAbsValMap&_varToValMap, LocToAbsValMap&_locToValMap) : AbstractState(_varToValMap, _locToValMap) {}
453
+
454
+ /// copy constructor
455
+ SparseAbstractState(const SparseAbstractState&rhs) : AbstractState(rhs)
456
+ {
457
+
458
+ }
459
+
460
+ virtual ~SparseAbstractState() = default;
461
+
462
+ SparseAbstractState&operator=(const SparseAbstractState&rhs)
463
+ {
464
+ AbstractState::operator=(rhs);
465
+ return *this;
466
+ }
467
+
468
+ virtual void printExprValues(std::ostream &oss) const;
469
+
470
+ /// move constructor
471
+ SparseAbstractState(SparseAbstractState&&rhs) : AbstractState(std::move(rhs))
472
+ {
473
+
474
+ }
475
+
476
+ /// operator= move constructor
477
+ SparseAbstractState&operator=(SparseAbstractState&&rhs)
478
+ {
479
+ AbstractState::operator=(std::move(rhs));
480
+ return *this;
481
+ }
482
+
483
+ public:
484
+
485
+ /// get memory addresses of variable
486
+ AbstractValue &getAddrs(u32_t id)
487
+ {
488
+ if (_varToAbsVal.find(id)!= _varToAbsVal.end())
489
+ {
490
+ return _varToAbsVal[id];
491
+ }
492
+ else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
493
+ {
494
+ return globalES._varToAbsVal[id];
495
+ }
496
+ else
497
+ {
498
+ globalES._varToAbsVal[id] = AddressValue();
499
+ return globalES._varToAbsVal[id];
500
+ }
501
+ }
502
+
503
+ /// get abstract value of variable
504
+ inline AbstractValue &operator[](u32_t varId)
505
+ {
506
+ auto localIt = _varToAbsVal.find(varId);
507
+ if(localIt != _varToAbsVal.end())
508
+ return localIt->second;
509
+ else
510
+ {
511
+ return globalES._varToAbsVal[varId];
512
+ }
513
+ }
514
+
515
+ /// whether the variable is in varToAddrs table
516
+ inline bool inVarToAddrsTable(u32_t id) const
517
+ {
518
+ if (_varToAbsVal.find(id)!= _varToAbsVal.end())
519
+ {
520
+ if (_varToAbsVal.at(id).isAddr())
521
+ {
522
+ return true;
523
+ }
524
+ else
525
+ {
526
+ return false;
527
+ }
528
+ }
529
+ else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
530
+ {
531
+ if (globalES._varToAbsVal[id].isAddr())
532
+ {
533
+ return true;
534
+ }
535
+ else
536
+ {
537
+ return false;
538
+ }
539
+ }
540
+ else
541
+ {
542
+ return false;
543
+ }
544
+ }
545
+
546
+ /// whether the variable is in varToVal table
547
+ inline bool inVarToValTable(u32_t id) const
548
+ {
549
+ if (_varToAbsVal.find(id)!= _varToAbsVal.end())
550
+ {
551
+ if (_varToAbsVal.at(id).isInterval())
552
+ {
553
+ return true;
554
+ }
555
+ else
556
+ {
557
+ return false;
558
+ }
559
+ }
560
+ else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
561
+ {
562
+ if (globalES._varToAbsVal[id].isInterval())
563
+ {
564
+ return true;
565
+ }
566
+ else
567
+ {
568
+ return false;
569
+ }
570
+ }
571
+ else
572
+ {
573
+ return false;
574
+ }
575
+ }
576
+
577
+ /// whether the memory address stores memory addresses
578
+ inline bool inLocToAddrsTable(u32_t id) const
579
+ {
580
+ if (_locToAbsVal.find(id)!= _locToAbsVal.end())
581
+ {
582
+ if (_locToAbsVal.at(id).isAddr())
583
+ {
584
+ return true;
585
+ }
586
+ else
587
+ {
588
+ return false;
589
+ }
590
+ }
591
+ else if (globalES._locToAbsVal.find(id)!= globalES._locToAbsVal.end())
592
+ {
593
+ if (globalES._locToAbsVal[id].isAddr())
594
+ {
595
+ return true;
596
+ }
597
+ else
598
+ {
599
+ return false;
600
+ }
601
+ }
602
+ else
603
+ {
604
+ return false;
605
+ }
606
+ }
607
+
608
+ /// whether the memory address stores abstract value
609
+ inline bool inLocToValTable(u32_t id) const
610
+ {
611
+ if (_locToAbsVal.find(id)!= _locToAbsVal.end())
612
+ {
613
+ if (_locToAbsVal.at(id).isInterval())
614
+ {
615
+ return true;
616
+ }
617
+ else
618
+ {
619
+ return false;
620
+ }
621
+ }
622
+ else if (globalES._locToAbsVal.find(id)!= globalES._locToAbsVal.end())
623
+ {
624
+ if (globalES._locToAbsVal[id].isInterval())
625
+ {
626
+ return true;
627
+ }
628
+ else
629
+ {
630
+ return false;
631
+ }
632
+ }
633
+ else
634
+ {
635
+ return false;
636
+ }
637
+ }
638
+
639
+ inline bool inLocalLocToValTable(u32_t id) const
640
+ {
641
+ if (_locToAbsVal.find(id)!= _locToAbsVal.end())
642
+ {
643
+ return _locToAbsVal.at(id).isInterval();
644
+ }
645
+ else
646
+ return false;
647
+ }
648
+
649
+ inline bool inLocalLocToAddrsTable(u32_t id) const
650
+ {
651
+ if (_locToAbsVal.find(id)!= _locToAbsVal.end())
652
+ {
653
+ return _locToAbsVal.at(id).isAddr();
654
+ }
655
+ else
656
+ return false;
657
+ }
658
+
659
+ public:
660
+
661
+ inline void cpyItvToLocal(u32_t varId)
662
+ {
663
+ auto localIt = _varToAbsVal.find(varId);
664
+ // local already have varId
665
+ if (localIt != _varToAbsVal.end()) return;
666
+ auto globIt = globalES._varToAbsVal.find(varId);
667
+ if (globIt != globalES._varToAbsVal.end())
668
+ {
669
+ _varToAbsVal[varId] = globIt->second;
670
+ }
671
+ }
672
+
673
+ /// domain widen with other, and return the widened domain
674
+ SparseAbstractState widening(const SparseAbstractState&other);
675
+
676
+ /// domain narrow with other, and return the narrowed domain
677
+ SparseAbstractState narrowing(const SparseAbstractState&other);
678
+
679
+ /// domain widen with other, important! other widen this.
680
+ void widenWith(const SparseAbstractState&other);
681
+
682
+ /// domain join with other, important! other widen this.
683
+ void joinWith(const SparseAbstractState&other);
684
+
685
+ /// domain narrow with other, important! other widen this.
686
+ void narrowWith(const SparseAbstractState&other);
687
+
688
+ /// domain meet with other, important! other widen this.
689
+ void meetWith(const SparseAbstractState&other);
690
+
691
+ u32_t hash() const;
692
+
693
+ public:
694
+
695
+ inline AbstractValue &load(u32_t addr)
696
+ {
697
+ assert(isVirtualMemAddress(addr) && "not virtual address?");
698
+ u32_t objId = getInternalID(addr);
699
+ auto it = _locToAbsVal.find(objId);
700
+ if(it != _locToAbsVal.end())
701
+ return it->second;
702
+ else
703
+ {
704
+ auto globIt = globalES._locToAbsVal.find(objId);
705
+ if(globIt != globalES._locToAbsVal.end())
706
+ return globIt->second;
707
+ else
708
+ {
709
+ return globalES._locToAbsVal[objId];
710
+ }
711
+
712
+ }
713
+ }
714
+
715
+ bool equals(const SparseAbstractState&other) const;
716
+
717
+ bool operator==(const SparseAbstractState&rhs) const
718
+ {
719
+ return eqVarToValMap(_varToAbsVal, rhs._varToAbsVal) &&
720
+ eqVarToValMap(_locToAbsVal, rhs._locToAbsVal);
721
+ }
722
+
723
+ bool operator!=(const SparseAbstractState&rhs) const
724
+ {
725
+ return !(*this == rhs);
726
+ }
727
+
728
+ bool operator<(const SparseAbstractState&rhs) const
729
+ {
730
+ return !(*this >= rhs);
731
+ }
732
+
733
+
734
+ bool operator>=(const SparseAbstractState&rhs) const
735
+ {
736
+ return geqVarToValMap(_varToAbsVal, rhs.getVarToVal()) && geqVarToValMap(_locToAbsVal, rhs._locToAbsVal);
737
+ }
738
+ };
739
+ }
740
+
741
+ template<>
742
+ struct std::hash<SVF::SparseAbstractState>
743
+ {
744
+ size_t operator()(const SVF::SparseAbstractState&exeState) const
745
+ {
746
+ return exeState.hash();
747
+ }
748
+ };
749
+
750
+ #endif //Z3_EXAMPLE_INTERVAL_DOMAIN_H