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 38 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 170 of file RelationSolver.cpp.

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

◆ beta()

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

Definition at line 245 of file RelationSolver.cpp.

247{
248 AbstractState res;
249 for (const auto& item : exeState.getVarToVal())
250 {
251 res[item.first] = IntervalValue(
252 sigma.at(item.first), sigma.at(item.first));
253 }
254 return res;
255}
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 36 of file RelationSolver.cpp.

38{
43 z3::solver solver = Z3Expr::getSolver();
44 z3::params p(Z3Expr::getContext());
46 p.set(":timeout", static_cast<unsigned>(600)); // in milliseconds
47 solver.set(p);
49
51 while (lower != upper)
52 {
54 {
56 }
57 else
58 {
60 }
63 solver.push();
64 solver.add(phi.getExpr() && rhs.getExpr());
66 z3::check_result checkRes = solver.check();
68 if (checkRes == z3::sat)
69 {
70 z3::model m = solver.get_model();
71 for (u32_t i = 0; i < m.size(); i++)
72 {
73 z3::func_decl v = m[i];
74 // assert(v.arity() == 0);
75 if (v.arity() != 0)
76 continue;
77 solution.emplace(std::stoi(v.name().str()),
78 m.get_const_interp(v).get_numeral_int());
79 }
80 for (const auto& item : domain.getVarToVal())
81 {
82 if (solution.find(item.first) == solution.end())
83 {
84 solution.emplace(item.first, 0);
85 }
86 }
87 solver.pop();
91 newLower.joinWith(rhs);
94 }
95 else
96 {
97 solver.pop();
98 if (checkRes == z3::unknown)
99 {
101 if (solver.reason_unknown() == "timeout")
102 return upper;
103 }
106 newUpper.meetWith(consequence);
107 upper = newUpper;
108 meets_in_a_row += 1;
109 }
110 }
111 return upper;
112}
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 345 of file RelationSolver.cpp.

346{
350 while (1)
351 {
352 L_phi.clear();
353 for (const auto& item : ret)
354 {
355 Z3Expr v = toIntZ3Expr(item.first);
356 if (low_values.at(item.first) <= (high_values.at(item.first)))
357 {
358 s32_t mid = (low_values.at(item.first) + (high_values.at(item.first) - low_values.at(item.first)) / 2);
359 updateMap(mid_values, item.first, mid);
360 Z3Expr expr = (toIntVal(mid) <= v && v <= toIntVal(high_values.at(item.first)));
361 L_phi[item.first] = expr;
362 }
363 }
364 if (L_phi.empty())
365 break;
366 else
368 }
369 return ret;
370}
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:47

◆ 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 270 of file RelationSolver.cpp.

271{
274 u32_t bias = 0;
275 s32_t infinity = INT32_MAX/2 - 1;
276
277 // int infinity = (INT32_MAX) - 1;
278 // int infinity = 20;
283 for (const auto& item: domain.getVarToVal())
284 {
285 IntervalValue interval = item.second.getInterval();
286 updateMap(ret, item.first, interval.ub().getIntNumeral());
287 if (interval.lb().is_minus_infinity())
289 else
290 updateMap(low_values, item.first, interval.lb().getIntNumeral());
291 if (interval.ub().is_plus_infinity())
293 else
294 updateMap(high_values, item.first, interval.ub().getIntNumeral());
295 if (item.first > bias)
296 bias = item.first + 1;
297 }
298 for (const auto& item: domain.getVarToVal())
299 {
301 IntervalValue interval = item.second.getInterval();
302 u32_t reverse_key = item.first + bias;
303 updateMap(ret, reverse_key, -interval.lb().getIntNumeral());
304 if (interval.ub().is_plus_infinity())
306 else
308 if (interval.lb().is_minus_infinity())
310 else
313 new_phi = (new_phi && (toIntZ3Expr(reverse_key) == -1 * toIntZ3Expr(item.first)));
314 }
316 BoxedOptSolver(new_phi.simplify(), ret, low_values, high_values);
319 for (const auto& item: ret)
320 {
321 if (item.first >= bias)
322 {
323 if (!retInv.inVarToValTable(item.first-bias))
325
326 if (item.second == (infinity))
328 retInv[item.first - bias].getInterval().ub());
329 else
330 retInv[item.first - bias] = IntervalValue(float(-item.second), retInv[item.first - bias].getInterval().ub());
331
332 }
333 else
334 {
335 if (item.second == (infinity))
336 retInv[item.first] = IntervalValue(retInv[item.first].getInterval().lb(),
338 else
339 retInv[item.first] = IntervalValue(retInv[item.first].getInterval().lb(), float(item.second));
340 }
341 }
342 return retInv;
343}
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 373 of file RelationSolver.cpp.

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

◆ gamma_hat() [1/3]

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

Return Z3Expr according to another valToValMap.

Definition at line 216 of file RelationSolver.cpp.

218{
220 for (auto& item : exeState.getVarToVal())
221 {
222 IntervalValue interval = alpha[item.first].getInterval();
223 if (interval.isBottom())
224 return Z3Expr::getContext().bool_val(false);
225 if (interval.isTop())
226 continue;
227 Z3Expr v = toIntZ3Expr(item.first);
228 res = (res && v >= (int)interval.lb().getNumeral() &&
229 v <= (int)interval.ub().getNumeral()).simplify();
230 }
231 return res;
232}
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 199 of file RelationSolver.cpp.

200{
202 for (auto& item : exeState.getVarToVal())
203 {
204 IntervalValue interval = item.second.getInterval();
205 if (interval.isBottom())
206 return Z3Expr::getContext().bool_val(false);
207 if (interval.isTop())
208 continue;
209 Z3Expr v = toIntZ3Expr(item.first);
210 res = (res && v >= (int)interval.lb().getNumeral() &&
211 v <= (int)interval.ub().getNumeral()).simplify();
212 }
213 return res;
214}

◆ gamma_hat() [3/3]

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

Return Z3Expr from a NodeID.

Definition at line 234 of file RelationSolver.cpp.

235{
236 auto it = exeState.getVarToVal().find(id);
237 assert(it != exeState.getVarToVal().end() && "id not in varToVal?");
238 Z3Expr v = toIntZ3Expr(id);
239 // Z3Expr v = Z3Expr::getContext().int_const(std::to_string(id).c_str());
240 Z3Expr res = (v >= (int)it->second.getInterval().lb().getNumeral() &&
241 v <= (int)it->second.getInterval().ub().getNumeral());
242 return res;
243}

◆ 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 114 of file RelationSolver.cpp.

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

◆ toIntVal()

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

Definition at line 66 of file RelationSolver.h.

67 {
68 return Z3Expr::getContext().int_val(f);
69 }

◆ toIntZ3Expr()

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

Return Z3 expression lazily based on SVFVar ID.

Definition at line 61 of file RelationSolver.h.

62 {
63 return Z3Expr::getContext().int_const(std::to_string(varId).c_str());
64 }

◆ toRealVal()

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

Definition at line 70 of file RelationSolver.h.

71 {
72 return Z3Expr::getContext().real_val(std::to_string(f.getFVal()).c_str());
73 }

◆ updateMap()

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

Definition at line 257 of file RelationSolver.cpp.

258{
259 auto it = map.find(key);
260 if (it == map.end())
261 {
262 map.emplace(key, value);
263 }
264 else
265 {
266 it->second = value;
267 }
268}

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