Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | List of all members
SVF::RelationSolver Class Reference

#include <RelationSolver.h>

Public Member Functions

 RelationSolver ()=default
 
Z3Expr gamma_hat (const AbstractState &exeState) const
 Return Z3Expr according to valToValMap.
 
Z3Expr gamma_hat (const AbstractState &alpha, const AbstractState &exeState) const
 Return Z3Expr according to another valToValMap.
 
Z3Expr gamma_hat (u32_t id, const AbstractState &exeState) const
 Return Z3Expr from a NodeID.
 
AbstractState abstract_consequence (const AbstractState &lower, const AbstractState &upper, const AbstractState &domain) const
 
AbstractState beta (const Map< u32_t, s32_t > &sigma, const AbstractState &exeState) const
 
virtual Z3Expr toIntZ3Expr (u32_t varId) const
 Return Z3 expression lazily based on SVFVar ID.
 
Z3Expr toIntVal (s32_t f) const
 
Z3Expr toRealVal (BoundedDouble f) const
 
AbstractState bilateral (const AbstractState &domain, const Z3Expr &phi, u32_t descend_check=0)
 
AbstractState RSY (const AbstractState &domain, const Z3Expr &phi)
 
Map< u32_t, s32_tBoxedOptSolver (const Z3Expr &phi, Map< u32_t, s32_t > &ret, Map< u32_t, s32_t > &low_values, Map< u32_t, s32_t > &high_values)
 
AbstractState BS (const AbstractState &domain, const Z3Expr &phi)
 
void updateMap (Map< u32_t, s32_t > &map, u32_t key, const s32_t &value)
 
void decide_cpa_ext (const Z3Expr &phi, Map< u32_t, Z3Expr > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &)
 

Detailed Description

Definition at line 42 of file RelationSolver.h.

Constructor & Destructor Documentation

◆ RelationSolver()

SVF::RelationSolver::RelationSolver ( )
default

Member Function Documentation

◆ abstract_consequence()

AbstractState RelationSolver::abstract_consequence ( const AbstractState lower,
const AbstractState upper,
const AbstractState domain 
) const

for variable in self.variables:

proposed = self.top.copy()

proposed.set_interval(variable, lower.interval_of(variable)) proposed._locToItvVal

if not proposed >= upper:

return proposed

return lower.copy()

Definition at line 176 of file RelationSolver.cpp.

178{
179 /*Returns the "abstract consequence" of lower and upper.
180
181 The abstract consequence must be a superset of lower and *NOT* a
182 superset of upper.
183
184 Note that this is a fairly "simple" abstract consequence, in that it
185 sets only one variable to a non-top interval. This improves performance
186 of the SMT solver in many cases. In certain cases, other choices for
187 the abstract consequence will lead to better algorithm performance.*/
188
189 for (auto it = domain.getVarToVal().begin();
190 it != domain.getVarToVal().end(); ++it)
192 {
194 proposed[it->first] = lower[it->first].getInterval();
197 if (!(proposed >= upper))
198 {
199 return proposed;
200 }
201 }
202 return lower;
203}
AbstractState top() const
Set all value top.
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ beta()

AbstractState RelationSolver::beta ( const Map< u32_t, s32_t > &  sigma,
const AbstractState exeState 
) const

Definition at line 251 of file RelationSolver.cpp.

253{
254 AbstractState res;
255 for (const auto& item : exeState.getVarToVal())
256 {
257 res[item.first] = IntervalValue(
258 sigma.at(item.first), sigma.at(item.first));
259 }
260 return res;
261}
cJSON * item
Definition cJSON.h:222

◆ bilateral()

AbstractState RelationSolver::bilateral ( const AbstractState domain,
const Z3Expr phi,
u32_t  descend_check = 0 
)

init variables

TODO: add option for timeout

start processing

compute domain.model_and(phi, domain.logic_not(domain.gamma_hat(consequence)))

find any solution, which is sat

unknown or unsat

for timeout reason return upper

Definition at line 42 of file RelationSolver.cpp.

44{
49 z3::solver solver = Z3Expr::getSolver();
50 z3::params p(Z3Expr::getContext());
52 p.set(":timeout", static_cast<unsigned>(600)); // in milliseconds
53 solver.set(p);
55
57 while (lower != upper)
58 {
60 {
62 }
63 else
64 {
66 }
69 solver.push();
70 solver.add(phi.getExpr() && rhs.getExpr());
72 z3::check_result checkRes = solver.check();
74 if (checkRes == z3::sat)
75 {
76 z3::model m = solver.get_model();
77 for (u32_t i = 0; i < m.size(); i++)
78 {
79 z3::func_decl v = m[i];
80 // assert(v.arity() == 0);
81 if (v.arity() != 0)
82 continue;
83 solution.emplace(std::stoi(v.name().str()),
84 m.get_const_interp(v).get_numeral_int());
85 }
86 for (const auto& item : domain.getVarToVal())
87 {
88 if (solution.find(item.first) == solution.end())
89 {
90 solution.emplace(item.first, 0);
91 }
92 }
93 solver.pop();
97 newLower.joinWith(rhs);
100 }
101 else
102 {
103 solver.pop();
104 if (checkRes == z3::unknown)
105 {
107 if (solver.reason_unknown() == "timeout")
108 return upper;
109 }
112 newUpper.meetWith(consequence);
113 upper = newUpper;
114 meets_in_a_row += 1;
115 }
116 }
117 return upper;
118}
unsigned u32_t
Definition CommandLine.h:18
cJSON * p
Definition cJSON.cpp:2559
AbstractState bottom() const
Set all value bottom.
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
void meetWith(const AbstractState &other)
domain meet with other, important! other widen this.
Z3Expr gamma_hat(const AbstractState &exeState) const
Return Z3Expr according to valToValMap.
AbstractState beta(const Map< u32_t, s32_t > &sigma, const AbstractState &exeState) const
AbstractState abstract_consequence(const AbstractState &lower, const AbstractState &upper, const AbstractState &domain) const
static z3::solver & getSolver()
Get z3 solver, singleton design here to make sure we only have one context.
Definition Z3Expr.cpp:56
static z3::context & getContext()
Get z3 context, singleton design here to make sure we only have one context.
Definition Z3Expr.cpp:66

◆ BoxedOptSolver()

Map< u32_t, s32_t > RelationSolver::BoxedOptSolver ( const Z3Expr phi,
Map< u32_t, s32_t > &  ret,
Map< u32_t, s32_t > &  low_values,
Map< u32_t, s32_t > &  high_values 
)

this is the S in the original paper

Definition at line 351 of file RelationSolver.cpp.

352{
356 while (1)
357 {
358 L_phi.clear();
359 for (const auto& item : ret)
360 {
361 Z3Expr v = toIntZ3Expr(item.first);
362 if (low_values.at(item.first) <= (high_values.at(item.first)))
363 {
364 s32_t mid = (low_values.at(item.first) + (high_values.at(item.first) - low_values.at(item.first)) / 2);
365 updateMap(mid_values, item.first, mid);
366 Z3Expr expr = (toIntVal(mid) <= v && v <= toIntVal(high_values.at(item.first)));
367 L_phi[item.first] = expr;
368 }
369 }
370 if (L_phi.empty())
371 break;
372 else
374 }
375 return ret;
376}
virtual Z3Expr toIntZ3Expr(u32_t varId) const
Return Z3 expression lazily based on SVFVar ID.
void updateMap(Map< u32_t, s32_t > &map, u32_t key, const s32_t &value)
void decide_cpa_ext(const Z3Expr &phi, Map< u32_t, Z3Expr > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &, Map< u32_t, s32_t > &)
Z3Expr toIntVal(s32_t f) const
signed s32_t
Definition GeneralType.h:68

◆ BS()

AbstractState RelationSolver::BS ( const AbstractState domain,
const Z3Expr phi 
)

because key of _varToItvVal is u32_t, -key may out of range for int so we do key + bias for -key

init low, ret, high

init objects -x

add a relation that x == -(x+bias)

optimize each object

fill in the return values

Definition at line 276 of file RelationSolver.cpp.

277{
280 u32_t bias = 0;
281 s32_t infinity = INT32_MAX/2 - 1;
282
283 // int infinity = (INT32_MAX) - 1;
284 // int infinity = 20;
289 for (const auto& item: domain.getVarToVal())
290 {
291 IntervalValue interval = item.second.getInterval();
292 updateMap(ret, item.first, interval.ub().getIntNumeral());
293 if (interval.lb().is_minus_infinity())
295 else
296 updateMap(low_values, item.first, interval.lb().getIntNumeral());
297 if (interval.ub().is_plus_infinity())
299 else
300 updateMap(high_values, item.first, interval.ub().getIntNumeral());
301 if (item.first > bias)
302 bias = item.first + 1;
303 }
304 for (const auto& item: domain.getVarToVal())
305 {
307 IntervalValue interval = item.second.getInterval();
308 u32_t reverse_key = item.first + bias;
309 updateMap(ret, reverse_key, -interval.lb().getIntNumeral());
310 if (interval.ub().is_plus_infinity())
312 else
314 if (interval.lb().is_minus_infinity())
316 else
319 new_phi = (new_phi && (toIntZ3Expr(reverse_key) == -1 * toIntZ3Expr(item.first)));
320 }
322 BoxedOptSolver(new_phi.simplify(), ret, low_values, high_values);
325 for (const auto& item: ret)
326 {
327 if (item.first >= bias)
328 {
329 if (!retInv.inVarToValTable(item.first-bias))
331
332 if (item.second == (infinity))
334 retInv[item.first - bias].getInterval().ub());
335 else
336 retInv[item.first - bias] = IntervalValue(float(-item.second), retInv[item.first - bias].getInterval().ub());
337
338 }
339 else
340 {
341 if (item.second == (infinity))
342 retInv[item.first] = IntervalValue(retInv[item.first].getInterval().lb(),
344 else
345 retInv[item.first] = IntervalValue(retInv[item.first].getInterval().lb(), float(item.second));
346 }
347 }
348 return retInv;
349}
static BoundedInt plus_infinity()
bool is_minus_infinity() const
bool is_plus_infinity() const
s64_t getIntNumeral() const
static BoundedInt minus_infinity()
const BoundedInt & ub() const
Return the upper bound.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
Map< u32_t, s32_t > BoxedOptSolver(const Z3Expr &phi, Map< u32_t, s32_t > &ret, Map< u32_t, s32_t > &low_values, Map< u32_t, s32_t > &high_values)

◆ decide_cpa_ext()

void RelationSolver::decide_cpa_ext ( const Z3Expr phi,
Map< u32_t, Z3Expr > &  L_phi,
Map< u32_t, s32_t > &  mid_values,
Map< u32_t, s32_t > &  ret,
Map< u32_t, s32_t > &  low_values,
Map< u32_t, s32_t > &  high_values 
)

find any solution, which is sat

id is the var id, value is the solution found for var_id add a relation to check if the solution meets phi_id

unknown or unsat, we consider unknown as unsat

Definition at line 379 of file RelationSolver.cpp.

385{
386 while (1)
387 {
389 for (const auto& item : L_phi)
391 join_expr = (join_expr && phi).simplify();
392 z3::solver& solver = Z3Expr::getSolver();
393 solver.push();
394 solver.add(join_expr.getExpr());
396 z3::check_result checkRes = solver.check();
398 if (checkRes == z3::sat)
399 {
400 z3::model m = solver.get_model();
401 solver.pop();
402 for(const auto & item : L_phi)
403 {
404 u32_t id = item.first;
405 int value = m.eval(toIntZ3Expr(id).getExpr()).get_numeral_int();
406 // int value = m.eval(Z3Expr::getContext().int_const(std::to_string(id).c_str())).get_numeral_int();
409 Z3Expr expr = (item.second && toIntZ3Expr(id) == value);
410 solver.push();
411 solver.add(expr.getExpr());
412 // solution meets phi_id
413 if (solver.check() == z3::sat)
414 {
415 updateMap(ret, id, (value));
416 updateMap(low_values, id, ret.at(id) + 1);
417
418 s32_t mid = (low_values.at(id) + high_values.at(id) + 1) / 2;
420 Z3Expr v = toIntZ3Expr(id);
421 // Z3Expr v = Z3Expr::getContext().int_const(std::to_string(id).c_str());
422 Z3Expr expr = (toIntVal(mid_values.at(id)) <= v && v <= toIntVal(high_values.at(id)));
423 L_phi[id] = expr;
424 }
425 solver.pop();
426 }
427 }
428 else
429 {
430 solver.pop();
431 for (const auto& item : L_phi)
433 return;
434 }
435 }
436
437}

◆ gamma_hat() [1/3]

Z3Expr RelationSolver::gamma_hat ( const AbstractState alpha,
const AbstractState exeState 
) const

Return Z3Expr according to another valToValMap.

Definition at line 222 of file RelationSolver.cpp.

224{
226 for (auto& item : exeState.getVarToVal())
227 {
228 IntervalValue interval = alpha[item.first].getInterval();
229 if (interval.isBottom())
230 return Z3Expr::getContext().bool_val(false);
231 if (interval.isTop())
232 continue;
233 Z3Expr v = toIntZ3Expr(item.first);
234 res = (res && v >= (int)interval.lb().getNumeral() &&
235 v <= (int)interval.ub().getNumeral()).simplify();
236 }
237 return res;
238}
s64_t getNumeral() const
Retrieves the numeral value of the BoundedInt object.
bool isTop() const
bool isBottom() const

◆ gamma_hat() [2/3]

Z3Expr RelationSolver::gamma_hat ( const AbstractState exeState) const

Return Z3Expr according to valToValMap.

Definition at line 205 of file RelationSolver.cpp.

206{
208 for (auto& item : exeState.getVarToVal())
209 {
210 IntervalValue interval = item.second.getInterval();
211 if (interval.isBottom())
212 return Z3Expr::getContext().bool_val(false);
213 if (interval.isTop())
214 continue;
215 Z3Expr v = toIntZ3Expr(item.first);
216 res = (res && v >= (int)interval.lb().getNumeral() &&
217 v <= (int)interval.ub().getNumeral()).simplify();
218 }
219 return res;
220}

◆ gamma_hat() [3/3]

Z3Expr RelationSolver::gamma_hat ( u32_t  id,
const AbstractState exeState 
) const

Return Z3Expr from a NodeID.

Definition at line 240 of file RelationSolver.cpp.

241{
242 auto it = exeState.getVarToVal().find(id);
243 assert(it != exeState.getVarToVal().end() && "id not in varToVal?");
244 Z3Expr v = toIntZ3Expr(id);
245 // Z3Expr v = Z3Expr::getContext().int_const(std::to_string(id).c_str());
246 Z3Expr res = (v >= (int)it->second.getInterval().lb().getNumeral() &&
247 v <= (int)it->second.getInterval().ub().getNumeral());
248 return res;
249}

◆ RSY()

AbstractState RelationSolver::RSY ( const AbstractState domain,
const Z3Expr phi 
)

TODO: add option for timeout

find any solution, which is sat

unknown or unsat

for timeout reason return upper

Definition at line 120 of file RelationSolver.cpp.

121{
123 z3::solver& solver = Z3Expr::getSolver();
124 z3::params p(Z3Expr::getContext());
126 p.set(":timeout", static_cast<unsigned>(600)); // in milliseconds
127 solver.set(p);
128 while (1)
129 {
131 solver.push();
132 solver.add(phi.getExpr() && rhs.getExpr());
134 z3::check_result checkRes = solver.check();
136 if (checkRes == z3::sat)
137 {
138 z3::model m = solver.get_model();
139 for (u32_t i = 0; i < m.size(); i++)
140 {
141 z3::func_decl v = m[i];
142 if (v.arity() != 0)
143 continue;
144
145 solution.emplace(std::stoi(v.name().str()),
146 m.get_const_interp(v).get_numeral_int());
147 }
148 for (const auto& item : domain.getVarToVal())
149 {
150 if (solution.find(item.first) == solution.end())
151 {
152 solution.emplace(item.first, 0);
153 }
154 }
155 solver.pop();
158 newLower.joinWith(beta(solution, domain));
159 lower = newLower;
160 }
161 else
162 {
163 solver.pop();
164 if (checkRes == z3::unknown)
165 {
167 if (solver.reason_unknown() == "timeout")
168 return domain.top();
169 }
170 break;
171 }
172 }
173 return lower;
174}

◆ toIntVal()

Z3Expr SVF::RelationSolver::toIntVal ( s32_t  f) const
inline

Definition at line 70 of file RelationSolver.h.

71 {
72 return Z3Expr::getContext().int_val(f);
73 }

◆ toIntZ3Expr()

virtual Z3Expr SVF::RelationSolver::toIntZ3Expr ( u32_t  varId) const
inlinevirtual

Return Z3 expression lazily based on SVFVar ID.

Definition at line 65 of file RelationSolver.h.

66 {
67 return Z3Expr::getContext().int_const(std::to_string(varId).c_str());
68 }

◆ toRealVal()

Z3Expr SVF::RelationSolver::toRealVal ( BoundedDouble  f) const
inline

Definition at line 74 of file RelationSolver.h.

75 {
76 return Z3Expr::getContext().real_val(std::to_string(f.getFVal()).c_str());
77 }

◆ updateMap()

void RelationSolver::updateMap ( Map< u32_t, s32_t > &  map,
u32_t  key,
const s32_t value 
)

Definition at line 263 of file RelationSolver.cpp.

264{
265 auto it = map.find(key);
266 if (it == map.end())
267 {
268 map.emplace(key, value);
269 }
270 else
271 {
272 it->second = value;
273 }
274}

The documentation for this class was generated from the following files: