svf-tools 1.0.728 → 1.0.730
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/AbstractExecution/ConsExeState.h +446 -0
- package/svf/include/AbstractExecution/ExeState.h +72 -5
- package/svf/include/AbstractExecution/IntervalExeState.h +13 -0
- package/svf/include/AbstractExecution/SVFIR2ConsExeState.h +149 -0
- package/svf/include/AbstractExecution/SymState.h +221 -0
- package/svf/lib/AbstractExecution/ConsExeState.cpp +606 -0
- package/svf/lib/AbstractExecution/ExeState.cpp +16 -7
- package/svf/lib/AbstractExecution/SVFIR2ConsExeState.cpp +808 -0
- package/svf/lib/AbstractExecution/SymState.cpp +37 -0
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +23 -0
- package/svf-llvm/lib/CHGBuilder.cpp +2 -5
- package/svf-llvm/lib/DCHG.cpp +1 -2
- package/svf-llvm/lib/LLVMUtil.cpp +13 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
//===- ConsExeState.cpp ----Constant Execution State-------------------------//
|
|
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
|
+
//
|
|
24
|
+
// Created by jiawei and xiao on 6/1/23.
|
|
25
|
+
//
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
#include "AbstractExecution/ConsExeState.h"
|
|
30
|
+
#include <iomanip>
|
|
31
|
+
#include "Util/Options.h"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
using namespace SVF;
|
|
35
|
+
using namespace SVFUtil;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
ConsExeState ConsExeState::globalConsES(initExeState());
|
|
39
|
+
|
|
40
|
+
/*!
|
|
41
|
+
* Copy operator
|
|
42
|
+
* @param rhs
|
|
43
|
+
* @return
|
|
44
|
+
*/
|
|
45
|
+
ConsExeState &ConsExeState::operator=(const ConsExeState &rhs)
|
|
46
|
+
{
|
|
47
|
+
if (*this != rhs)
|
|
48
|
+
{
|
|
49
|
+
_varToVal = rhs.getVarToVal();
|
|
50
|
+
_locToVal = rhs.getLocToVal();
|
|
51
|
+
ExeState::operator=(rhs);
|
|
52
|
+
}
|
|
53
|
+
return *this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/*!
|
|
57
|
+
* Move operator
|
|
58
|
+
* @param rhs
|
|
59
|
+
* @return
|
|
60
|
+
*/
|
|
61
|
+
ConsExeState &ConsExeState::operator=(ConsExeState &&rhs) noexcept
|
|
62
|
+
{
|
|
63
|
+
if (this != &rhs)
|
|
64
|
+
{
|
|
65
|
+
_varToVal = SVFUtil::move(rhs._varToVal);
|
|
66
|
+
_locToVal = SVFUtil::move(rhs._locToVal);
|
|
67
|
+
ExeState::operator=(std::move(rhs));
|
|
68
|
+
}
|
|
69
|
+
return *this;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*!
|
|
73
|
+
* Overloading Operator==
|
|
74
|
+
* @param rhs
|
|
75
|
+
* @return
|
|
76
|
+
*/
|
|
77
|
+
bool ConsExeState::operator==(const ConsExeState &rhs) const
|
|
78
|
+
{
|
|
79
|
+
// if values of variables are not changed, fix-point is reached
|
|
80
|
+
return ExeState::operator==(rhs) && eqVarToValMap(_varToVal, rhs.getVarToVal()) &&
|
|
81
|
+
eqVarToValMap(_locToVal, rhs.getLocToVal());
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*!
|
|
85
|
+
* Overloading Operator<
|
|
86
|
+
* @param rhs
|
|
87
|
+
* @return
|
|
88
|
+
*/
|
|
89
|
+
bool ConsExeState::operator<(const ConsExeState &rhs) const
|
|
90
|
+
{
|
|
91
|
+
// judge from path constraint
|
|
92
|
+
if (lessThanVarToValMap(_varToVal, rhs.getVarToVal()) || lessThanVarToValMap(_locToVal, rhs.getLocToVal()))
|
|
93
|
+
return true;
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
u32_t ConsExeState::hash() const
|
|
98
|
+
{
|
|
99
|
+
size_t bas = ExeState::hash();
|
|
100
|
+
size_t h = getVarToVal().size() * 2;
|
|
101
|
+
SVF::Hash<SVF::u32_t> hf;
|
|
102
|
+
for (const auto &t: getVarToVal())
|
|
103
|
+
{
|
|
104
|
+
h ^= hf(t.first) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
105
|
+
h ^= hf(t.second.id()) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
size_t h2 = getVarToVal().size() * 2;
|
|
109
|
+
|
|
110
|
+
for (const auto &t: getLocToVal())
|
|
111
|
+
{
|
|
112
|
+
h2 ^= hf(t.first) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
|
|
113
|
+
h2 ^= hf(t.second.id()) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
|
|
114
|
+
}
|
|
115
|
+
SVF::Hash<std::pair<SVF::u32_t, SVF::u32_t>> pairH;
|
|
116
|
+
|
|
117
|
+
return pairH(std::make_pair(bas, pairH(std::make_pair(h, h2))));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*!
|
|
121
|
+
* Build global execution state
|
|
122
|
+
* @param globES
|
|
123
|
+
* @param vars
|
|
124
|
+
*/
|
|
125
|
+
void ConsExeState::buildGlobES(ConsExeState &globES, Set<u32_t> &vars)
|
|
126
|
+
{
|
|
127
|
+
for (const auto &varId: vars)
|
|
128
|
+
{
|
|
129
|
+
SingleAbsValue &expr = globES[varId];
|
|
130
|
+
if (expr.is_numeral() && isVirtualMemAddress(expr.get_numeral_int()))
|
|
131
|
+
{
|
|
132
|
+
if (globES.inLocalLocToVal(expr))
|
|
133
|
+
{
|
|
134
|
+
store(expr, globES.load(expr));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*!
|
|
141
|
+
* Merge rhs into this
|
|
142
|
+
* @param rhs
|
|
143
|
+
* @return
|
|
144
|
+
*/
|
|
145
|
+
bool ConsExeState::joinWith(const SVF::ConsExeState &rhs)
|
|
146
|
+
{
|
|
147
|
+
bool changed = ExeState::joinWith(rhs);
|
|
148
|
+
for (const auto &rhsItem: rhs._varToVal)
|
|
149
|
+
{
|
|
150
|
+
auto it = _varToVal.find(rhsItem.first);
|
|
151
|
+
// Intersection - lhs and rhs have the same var id
|
|
152
|
+
if (it != getVarToVal().end())
|
|
153
|
+
{
|
|
154
|
+
if (it->second.isTop() || rhsItem.second.isTop())
|
|
155
|
+
{
|
|
156
|
+
if (assign(it->second, SingleAbsValue::topConstant()))
|
|
157
|
+
changed = true;
|
|
158
|
+
}
|
|
159
|
+
else if (it->second.isBottom())
|
|
160
|
+
{
|
|
161
|
+
if (assign(it->second, rhsItem.second))
|
|
162
|
+
changed = true;
|
|
163
|
+
}
|
|
164
|
+
else if (rhsItem.second.isBottom())
|
|
165
|
+
{
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
else
|
|
169
|
+
{
|
|
170
|
+
if (!eq(it->second, rhsItem.second))
|
|
171
|
+
{
|
|
172
|
+
if (assign(it->second, SingleAbsValue::topConstant()))
|
|
173
|
+
changed = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else
|
|
178
|
+
{
|
|
179
|
+
_varToVal.emplace(rhsItem.first, rhsItem.second);
|
|
180
|
+
changed = true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (const auto &rhsItem: rhs._locToVal)
|
|
185
|
+
{
|
|
186
|
+
auto it = _locToVal.find(rhsItem.first);
|
|
187
|
+
// Intersection - lhs and rhs have the same var id
|
|
188
|
+
if (it != getLocToVal().end())
|
|
189
|
+
{
|
|
190
|
+
if (it->second.isTop() || rhsItem.second.isTop())
|
|
191
|
+
{
|
|
192
|
+
if (assign(it->second, SingleAbsValue::topConstant()))
|
|
193
|
+
changed = true;
|
|
194
|
+
}
|
|
195
|
+
else if (it->second.isBottom())
|
|
196
|
+
{
|
|
197
|
+
if (assign(it->second, rhsItem.second))
|
|
198
|
+
changed = true;
|
|
199
|
+
}
|
|
200
|
+
else if (rhsItem.second.isBottom())
|
|
201
|
+
{
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
else
|
|
205
|
+
{
|
|
206
|
+
if (!eq(it->second, rhsItem.second))
|
|
207
|
+
{
|
|
208
|
+
if (assign(it->second, SingleAbsValue::topConstant()))
|
|
209
|
+
changed = true;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else
|
|
214
|
+
{
|
|
215
|
+
_locToVal.emplace(rhsItem.first, rhsItem.second);
|
|
216
|
+
changed = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return changed;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/*!
|
|
223
|
+
* We should build a summary for each actual params to boost precision.
|
|
224
|
+
* The summary of callee only contains the side-effects of callee
|
|
225
|
+
* (input obj value, return value, global value) without irrelevant caller information.
|
|
226
|
+
* We apply the summary to the exestate at each callsite.
|
|
227
|
+
* @param summary
|
|
228
|
+
*/
|
|
229
|
+
void ConsExeState::applySummary(const ConsExeState &summary)
|
|
230
|
+
{
|
|
231
|
+
for (const auto &item: summary._varToVal)
|
|
232
|
+
{
|
|
233
|
+
_varToVal[item.first] = item.second;
|
|
234
|
+
}
|
|
235
|
+
for (const auto &item: summary._locToVal)
|
|
236
|
+
{
|
|
237
|
+
_locToVal[item.first] = item.second;
|
|
238
|
+
}
|
|
239
|
+
for (const auto &item: summary._varToVAddrs)
|
|
240
|
+
{
|
|
241
|
+
_varToVAddrs[item.first] = item.second;
|
|
242
|
+
}
|
|
243
|
+
for (const auto &item: summary._locToVAddrs)
|
|
244
|
+
{
|
|
245
|
+
_locToVAddrs[item.first] = item.second;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/*!
|
|
250
|
+
* Print values of all expressions
|
|
251
|
+
*/
|
|
252
|
+
void ConsExeState::printExprValues() const
|
|
253
|
+
{
|
|
254
|
+
std::cout << "\n";
|
|
255
|
+
std::cout.flags(std::ios::left);
|
|
256
|
+
std::cout << "\t-----------------Var and Value-----------------\n";
|
|
257
|
+
for (const auto &item: getVarToVal())
|
|
258
|
+
{
|
|
259
|
+
std::stringstream exprName;
|
|
260
|
+
exprName << "\tVar" << item.first;
|
|
261
|
+
std::cout << std::setw(20) << exprName.str();
|
|
262
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
263
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
264
|
+
{
|
|
265
|
+
std::cout << "\t\t Value: " << std::hex << "0x" << z3Expr2NumValue(sim) << "\n";
|
|
266
|
+
}
|
|
267
|
+
else
|
|
268
|
+
{
|
|
269
|
+
std::cout << "\t\t Value: " << std::dec << sim << "\n";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
std::cout << "\t-----------------------------------------------\n";
|
|
273
|
+
std::cout << "\t-----------------Loc and Value-----------------\n";
|
|
274
|
+
for (const auto &item: getLocToVal())
|
|
275
|
+
{
|
|
276
|
+
std::stringstream exprName;
|
|
277
|
+
exprName << "\tVar" << item.first;
|
|
278
|
+
std::cout << std::setw(20) << exprName.str();
|
|
279
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
280
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
281
|
+
{
|
|
282
|
+
std::cout << "\t\t Value: " << std::hex << "0x" << z3Expr2NumValue(sim) << "\n";
|
|
283
|
+
}
|
|
284
|
+
else
|
|
285
|
+
{
|
|
286
|
+
std::cout << "\t\t Value: " << std::dec << sim << "\n";
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
std::cout << "\t-----------------------------------------------\n";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
void ConsExeState::printExprValues(std::ostream &oss) const
|
|
293
|
+
{
|
|
294
|
+
oss << "\n";
|
|
295
|
+
oss.flags(std::ios::left);
|
|
296
|
+
oss << "\t-----------------Var and Value-----------------\n";
|
|
297
|
+
for (const auto &item: getVarToVal())
|
|
298
|
+
{
|
|
299
|
+
std::stringstream exprName;
|
|
300
|
+
exprName << "\tVar" << item.first;
|
|
301
|
+
oss << std::setw(20) << exprName.str();
|
|
302
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
303
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
304
|
+
{
|
|
305
|
+
oss << "\t\t Value: " << std::hex << "0x" << z3Expr2NumValue(sim) << "\n";
|
|
306
|
+
}
|
|
307
|
+
else
|
|
308
|
+
{
|
|
309
|
+
oss << "\t\t Value: " << std::dec << sim << "\n";
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
oss << "\t-----------------------------------------------\n";
|
|
313
|
+
oss << "\t-----------------Loc and Value-----------------\n";
|
|
314
|
+
for (const auto &item: getLocToVal())
|
|
315
|
+
{
|
|
316
|
+
std::stringstream exprName;
|
|
317
|
+
exprName << "\tVar" << item.first;
|
|
318
|
+
oss << std::setw(20) << exprName.str();
|
|
319
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
320
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
321
|
+
{
|
|
322
|
+
oss << "\t\t Value: " << std::hex << "0x" << z3Expr2NumValue(sim) << "\n";
|
|
323
|
+
}
|
|
324
|
+
else
|
|
325
|
+
{
|
|
326
|
+
oss << "\t\t Value: " << std::dec << sim << "\n";
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
oss << "\t-----------------------------------------------\n";
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
std::string ConsExeState::pcToString() const
|
|
333
|
+
{
|
|
334
|
+
std::stringstream exprName;
|
|
335
|
+
exprName << "Path Constraint:\n";
|
|
336
|
+
return SVFUtil::move(exprName.str());
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
std::string ConsExeState::varToString(u32_t valId) const
|
|
340
|
+
{
|
|
341
|
+
std::stringstream exprName;
|
|
342
|
+
auto it = getVarToVal().find(valId);
|
|
343
|
+
if (it == getVarToVal().end())
|
|
344
|
+
{
|
|
345
|
+
auto it2 = globalConsES._varToVal.find(valId);
|
|
346
|
+
if (it2 == globalConsES._varToVal.end())
|
|
347
|
+
{
|
|
348
|
+
exprName << "Var not in varToVal!\n";
|
|
349
|
+
}
|
|
350
|
+
else
|
|
351
|
+
{
|
|
352
|
+
const SingleAbsValue &sim = it2->second.simplify();
|
|
353
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
354
|
+
{
|
|
355
|
+
exprName << "addr: " << std::dec << getInternalID(z3Expr2NumValue(sim)) << "\n";
|
|
356
|
+
}
|
|
357
|
+
else
|
|
358
|
+
{
|
|
359
|
+
if (sim.is_numeral())
|
|
360
|
+
exprName << std::dec << z3Expr2NumValue(sim) << "\n";
|
|
361
|
+
else
|
|
362
|
+
exprName << sim.to_string() << "\n";
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else
|
|
367
|
+
{
|
|
368
|
+
const SingleAbsValue &sim = it->second.simplify();
|
|
369
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
370
|
+
{
|
|
371
|
+
exprName << "addr: " << std::dec << getInternalID(z3Expr2NumValue(sim)) << "\n";
|
|
372
|
+
}
|
|
373
|
+
else
|
|
374
|
+
{
|
|
375
|
+
if (sim.is_numeral())
|
|
376
|
+
exprName << std::dec << z3Expr2NumValue(sim) << "\n";
|
|
377
|
+
else
|
|
378
|
+
exprName << sim.to_string() << "\n";
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return SVFUtil::move(exprName.str());
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
std::string ConsExeState::locToString(u32_t objId) const
|
|
385
|
+
{
|
|
386
|
+
std::stringstream exprName;
|
|
387
|
+
auto it = getLocToVal().find(objId);
|
|
388
|
+
if (it == getLocToVal().end())
|
|
389
|
+
{
|
|
390
|
+
exprName << "Obj not in locToVal!\n";
|
|
391
|
+
}
|
|
392
|
+
else
|
|
393
|
+
{
|
|
394
|
+
const SingleAbsValue &sim = it->second.simplify();
|
|
395
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
396
|
+
{
|
|
397
|
+
exprName << "addr: " << std::dec << getInternalID(z3Expr2NumValue(sim)) << "\n";
|
|
398
|
+
}
|
|
399
|
+
else
|
|
400
|
+
{
|
|
401
|
+
if (sim.is_numeral())
|
|
402
|
+
exprName << std::dec << z3Expr2NumValue(sim) << "\n";
|
|
403
|
+
else
|
|
404
|
+
exprName << sim.to_string() << "\n";
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return SVFUtil::move(exprName.str());
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
std::string ConsExeState::toString() const
|
|
411
|
+
{
|
|
412
|
+
std::stringstream exprName;
|
|
413
|
+
exprName << pcToString();
|
|
414
|
+
exprName << "VarToVal:\n";
|
|
415
|
+
for (const auto &item: getVarToVal())
|
|
416
|
+
{
|
|
417
|
+
exprName << "Var" << std::to_string(item.first) << ":\n";
|
|
418
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
419
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
420
|
+
{
|
|
421
|
+
exprName << " \tValue" << std::dec << getInternalID(z3Expr2NumValue(sim)) << "\n";
|
|
422
|
+
}
|
|
423
|
+
else
|
|
424
|
+
{
|
|
425
|
+
exprName << " \tValue" << std::dec << z3Expr2NumValue(sim) << "\n";
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
exprName << "LocToVal:\n";
|
|
430
|
+
for (const auto &item: getLocToVal())
|
|
431
|
+
{
|
|
432
|
+
exprName << "Var" << std::to_string(item.first) << ":\n";
|
|
433
|
+
const SingleAbsValue &sim = item.second.simplify();
|
|
434
|
+
if (sim.is_numeral() && isVirtualMemAddress(z3Expr2NumValue(sim)))
|
|
435
|
+
{
|
|
436
|
+
exprName << " \tValue" << std::dec << getInternalID(z3Expr2NumValue(sim)) << "\n";
|
|
437
|
+
}
|
|
438
|
+
else
|
|
439
|
+
{
|
|
440
|
+
exprName << " \tValue" << std::dec << z3Expr2NumValue(sim) << "\n";
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return SVFUtil::move(exprName.str());
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
bool ConsExeState::applySelect(u32_t res, u32_t cond, u32_t top, u32_t fop)
|
|
447
|
+
{
|
|
448
|
+
if (inVarToVal(top) && inVarToVal(fop) && inVarToVal(cond))
|
|
449
|
+
{
|
|
450
|
+
SingleAbsValue &tExpr = (*this)[top], &fExpr = (*this)[fop], &condExpr = (*this)[cond];
|
|
451
|
+
|
|
452
|
+
return assign((*this)[res], ite(condExpr == 1, tExpr, fExpr));
|
|
453
|
+
}
|
|
454
|
+
else if (inVarToAddrsTable(top) && inVarToAddrsTable(fop) && inVarToVal(cond))
|
|
455
|
+
{
|
|
456
|
+
SingleAbsValue &condExpr = (*this)[cond];
|
|
457
|
+
if (condExpr.is_numeral())
|
|
458
|
+
{
|
|
459
|
+
getVAddrs(res) = condExpr.is_zero() ? getVAddrs(fop) : getVAddrs(top);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
bool ConsExeState::applyPhi(u32_t res, std::vector<u32_t> &ops)
|
|
466
|
+
{
|
|
467
|
+
for (u32_t i = 0; i < ops.size(); i++)
|
|
468
|
+
{
|
|
469
|
+
NodeID curId = ops[i];
|
|
470
|
+
if (inVarToVal(curId))
|
|
471
|
+
{
|
|
472
|
+
const SingleAbsValue &cur = (*this)[curId];
|
|
473
|
+
if (!inVarToVal(res))
|
|
474
|
+
{
|
|
475
|
+
(*this)[res] = cur;
|
|
476
|
+
}
|
|
477
|
+
else
|
|
478
|
+
{
|
|
479
|
+
(*this)[res].join_with(cur);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
else if (inVarToAddrsTable(curId))
|
|
483
|
+
{
|
|
484
|
+
const VAddrs &cur = getVAddrs(curId);
|
|
485
|
+
if (!inVarToAddrsTable(res))
|
|
486
|
+
{
|
|
487
|
+
getVAddrs(res) = cur;
|
|
488
|
+
}
|
|
489
|
+
else
|
|
490
|
+
{
|
|
491
|
+
getVAddrs(res).join_with(cur);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
s64_t ConsExeState::getNumber(u32_t lhs)
|
|
499
|
+
{
|
|
500
|
+
return z3Expr2NumValue((*this)[lhs]);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/*!
|
|
504
|
+
* Store value to location
|
|
505
|
+
* @param loc location, e.g., int_val(0x7f..01)
|
|
506
|
+
* @param value
|
|
507
|
+
*/
|
|
508
|
+
bool ConsExeState::store(const SingleAbsValue &loc, const SingleAbsValue &value)
|
|
509
|
+
{
|
|
510
|
+
assert(loc.is_numeral() && "location must be numeral");
|
|
511
|
+
s32_t virAddr = z3Expr2NumValue(loc);
|
|
512
|
+
assert(isVirtualMemAddress(virAddr) && "Pointer operand is not a physical address?");
|
|
513
|
+
return store(getInternalID(virAddr), value);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/*!
|
|
517
|
+
* Load value at location
|
|
518
|
+
* @param loc location, e.g., int_val(0x7f..01)
|
|
519
|
+
* @return
|
|
520
|
+
*/
|
|
521
|
+
SingleAbsValue ConsExeState::load(const SingleAbsValue &loc)
|
|
522
|
+
{
|
|
523
|
+
assert(loc.is_numeral() && "location must be numeral");
|
|
524
|
+
s32_t virAddr = z3Expr2NumValue(loc);
|
|
525
|
+
assert(isVirtualMemAddress(virAddr) && "Pointer operand is not a physical address?");
|
|
526
|
+
u32_t objId = getInternalID(virAddr);
|
|
527
|
+
assert(getInternalID(objId) == objId && "SVFVar idx overflow > 0x7f000000?");
|
|
528
|
+
return load(objId);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
/*!
|
|
533
|
+
* Whether two var to value map is equivalent
|
|
534
|
+
* @param pre
|
|
535
|
+
* @param nxt
|
|
536
|
+
* @return
|
|
537
|
+
*/
|
|
538
|
+
bool ConsExeState::eqVarToValMap(const VarToValMap &pre, const VarToValMap &nxt)
|
|
539
|
+
{
|
|
540
|
+
if (pre.size() != nxt.size()) return false;
|
|
541
|
+
for (const auto &item: nxt)
|
|
542
|
+
{
|
|
543
|
+
auto it = pre.find(item.first);
|
|
544
|
+
// return false if SVFVar not exists in rhs
|
|
545
|
+
if (it == pre.end())
|
|
546
|
+
return false;
|
|
547
|
+
if (!eq(it->second, item.second))
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/*!
|
|
554
|
+
* Whether lhs is less than rhs
|
|
555
|
+
* @param lhs
|
|
556
|
+
* @param rhs
|
|
557
|
+
* @return
|
|
558
|
+
*/
|
|
559
|
+
bool ConsExeState::lessThanVarToValMap(const VarToValMap &lhs, const VarToValMap &rhs)
|
|
560
|
+
{
|
|
561
|
+
if (lhs.size() != rhs.size()) return lhs.size() < rhs.size();
|
|
562
|
+
for (const auto &item: lhs)
|
|
563
|
+
{
|
|
564
|
+
auto it = rhs.find(item.first);
|
|
565
|
+
// lhs > rhs if SVFVar not exists in rhs
|
|
566
|
+
if (it == rhs.end())
|
|
567
|
+
return false;
|
|
568
|
+
// judge from expr id
|
|
569
|
+
if (!eq(item.second, it->second))
|
|
570
|
+
return item.second.id() < it->second.id();
|
|
571
|
+
}
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
SingleAbsValue ConsExeState::load(u32_t objId)
|
|
576
|
+
{
|
|
577
|
+
auto it = _locToVal.find(objId);
|
|
578
|
+
if (it != _locToVal.end())
|
|
579
|
+
{
|
|
580
|
+
return it->second;
|
|
581
|
+
}
|
|
582
|
+
else
|
|
583
|
+
{
|
|
584
|
+
auto globIt = globalConsES._locToVal.find(objId);
|
|
585
|
+
if (globIt != globalConsES._locToVal.end())
|
|
586
|
+
return globIt->second;
|
|
587
|
+
else
|
|
588
|
+
{
|
|
589
|
+
SVFUtil::writeWrnMsg("Null dereference");
|
|
590
|
+
return SingleAbsValue::topConstant();
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
bool ConsExeState::assign(SingleAbsValue &lhs, const SingleAbsValue &rhs)
|
|
596
|
+
{
|
|
597
|
+
if (!eq(lhs, rhs))
|
|
598
|
+
{
|
|
599
|
+
lhs = rhs;
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
else
|
|
603
|
+
{
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
@@ -37,18 +37,21 @@ bool ExeState::operator==(const ExeState &rhs) const
|
|
|
37
37
|
return eqVarToVAddrs(_varToVAddrs, rhs._varToVAddrs) && eqVarToVAddrs(_locToVAddrs, rhs._locToVAddrs);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
bool ExeState::joinWith(const ExeState &other)
|
|
41
41
|
{
|
|
42
|
+
bool changed = false;
|
|
42
43
|
for (auto it = other._varToVAddrs.begin(); it != other._varToVAddrs.end(); ++it)
|
|
43
44
|
{
|
|
44
45
|
auto key = it->first;
|
|
45
46
|
auto oit = _varToVAddrs.find(key);
|
|
46
47
|
if (oit != _varToVAddrs.end())
|
|
47
48
|
{
|
|
48
|
-
oit->second.join_with(it->second)
|
|
49
|
+
if(oit->second.join_with(it->second))
|
|
50
|
+
changed = true;
|
|
49
51
|
}
|
|
50
52
|
else
|
|
51
53
|
{
|
|
54
|
+
changed = true;
|
|
52
55
|
_varToVAddrs.emplace(key, it->second);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
@@ -58,25 +61,29 @@ void ExeState::joinWith(const ExeState &other)
|
|
|
58
61
|
auto oit = _locToVAddrs.find(key);
|
|
59
62
|
if (oit != _locToVAddrs.end())
|
|
60
63
|
{
|
|
61
|
-
oit->second.join_with(it->second)
|
|
64
|
+
if(oit->second.join_with(it->second))
|
|
65
|
+
changed = true;
|
|
62
66
|
}
|
|
63
67
|
else
|
|
64
68
|
{
|
|
69
|
+
changed = true;
|
|
65
70
|
_locToVAddrs.emplace(key, it->second);
|
|
66
71
|
}
|
|
67
72
|
}
|
|
73
|
+
return changed;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
void ExeState::meetWith(const ExeState &other)
|
|
76
|
+
bool ExeState::meetWith(const ExeState &other)
|
|
72
77
|
{
|
|
78
|
+
bool changed = false;
|
|
73
79
|
for (auto it = other._varToVAddrs.begin(); it != other._varToVAddrs.end(); ++it)
|
|
74
80
|
{
|
|
75
81
|
auto key = it->first;
|
|
76
82
|
auto oit = _varToVAddrs.find(key);
|
|
77
83
|
if (oit != _varToVAddrs.end())
|
|
78
84
|
{
|
|
79
|
-
oit->second.meet_with(it->second)
|
|
85
|
+
if(oit->second.meet_with(it->second))
|
|
86
|
+
changed = true;
|
|
80
87
|
}
|
|
81
88
|
}
|
|
82
89
|
for (auto it = other._locToVAddrs.begin(); it != other._locToVAddrs.end(); ++it)
|
|
@@ -85,9 +92,11 @@ void ExeState::meetWith(const ExeState &other)
|
|
|
85
92
|
auto oit = _locToVAddrs.find(key);
|
|
86
93
|
if (oit != _locToVAddrs.end())
|
|
87
94
|
{
|
|
88
|
-
oit->second.meet_with(it->second)
|
|
95
|
+
if(oit->second.meet_with(it->second))
|
|
96
|
+
changed = true;
|
|
89
97
|
}
|
|
90
98
|
}
|
|
99
|
+
return changed;
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
u32_t ExeState::hash() const
|