def verify_solution(ez, X_star,symbolTable,printModel=False): assert isinstance(symbolTable, collections.OrderedDict) assert isinstance(ez, z3.ExprRef) assert len(symbolTable)==X_star.size model=[] # (sympy.Symbol('x'), for (s,val) in zip(symbolTable.items(), X_star): var, sort = s[0],s[1] var=rename_var(var) # if ("!" in varr) or ("@" in var): # symVar="x_"+str(expr_z3.hash()) STOP HERE if sort == Sort.Float32: var_z3=z3.FP(str(var),z3.Float32()) val_z3=z3.FPVal(val,z3.Float32()) elif sort == Sort.Float64: var_z3=z3.FP(str(var),z3.Float64()) val_z3=z3.FPVal(val,z3.Float64()) else: raise NotImplementedError("Unexpected type %s" %sort) model.append((var_z3,val_z3)) if printModel: print "model: " print model ##Nice for debugging. #print "p"*90 #print z3.substitute(ez, *model) return _is_true(z3.simplify(z3.substitute(ez, *model)))
def visit_float_is_infinite(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = arg.sort() pos_inf = None neg_inf = None if self._is_float32_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float32()) neg_inf = z3.fpMinusInfinity(z3.Float32()) elif self._is_float64_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float64()) neg_inf = z3.fpMinusInfinity(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isInfinite op case') temp = z3.Or(z3.fpEQ(arg, pos_inf), z3.fpEQ(arg, neg_inf)) self.visit(temp)
def gen_symbolic_value(var_type, name): if var_type == bin_format.i32: return z3.BitVec(name, 32) if var_type == bin_format.i64: return z3.BitVec(name, 64) if var_type == bin_format.f32: return z3.FP(f'f32_{i}', z3.Float32()) if var_type == bin_format.f64: return z3.FP(name, z3.Float64()) raise TypeError('Unsupported variable type')
def fp_size_to_sort(size): size_class = z3.Float64() if size == 16: size_class = z3.Float16() elif size == 32: size_class = z3.Float32() elif size == 128: size_class = z3.Float128() return size_class
def _getSort(expr_z3): assert isinstance(expr_z3, z3.ExprRef) if expr_z3.sort() == z3.Float32(): return Sort.Float32 if expr_z3.sort() == z3.Float64(): return Sort.Float64 if expr_z3.sort() == z3.RealSort(): return Sort.Real if expr_z3.sort() == z3.IntSort(): return Sort.Int return Sort.UNKNOWN
def verify_solution(ez, X_star, symbolTable, printModel=False): assert isinstance(symbolTable, collections.OrderedDict) assert isinstance(ez, z3.ExprRef) assert isinstance(res, op.OptimizeResult) assert len(symbolTable) == X_star.size model = [] # (sympy.Symbol('x'), for (s, val) in zip(symbolTable.items(), X_star): var, sort = s[0], s[1] if sort == Sort.Float32: var_z3 = z3.FP(str(var), z3.Float32()) val_z3 = z3.FPVal(val, z3.Float32()) elif sort == Sort.Float64: var_z3 = z3.FP(str(var), z3.Float64()) val_z3 = z3.FPVal(val, z3.Float64()) else: raise NotImplementedError("Unexpected type %s" % sort) model.append((var_z3, val_z3)) if printModel: print "model: " print model return _is_true(z3.simplify(z3.substitute(ez, *model)))
def _ty_sort(ty): 'Translate a Type expression to a Z3 Sort' if isinstance(ty, IntType): return z3.BitVecSort(ty.width) return { PtrType: z3.BitVecSort(64), HalfType: z3.FloatHalf(), SingleType: z3.Float32(), DoubleType: z3.Float64(), FP128Type: z3.Float128(), X86FP80Type: z3.FPSort(15, 64), }[type(ty)]
def visit_float_is_positive(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = e.arg(0).sort() zero = None # FIXME: This isn't sound. We can't distinguish +0 and -0 # in Coral's constraint language self._unsound_translation('fp.isPositive') if self._is_float32_sort(arg_sort): zero = z3.fpPlusZero(z3.Float32()) elif self._is_float64_sort(arg_sort): zero = z3.fpPlusZero(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isPositive case') tmp = z3.fpGT(arg, zero) self.visit(tmp)
def visit_float_is_zero(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = arg.sort() zero = None # It doesn't matter if we pick +0 or -0 as we are using # the fp.eq operator which can't distinguish them, so # the choice of +0 is arbitrary. if self._is_float32_sort(arg_sort): zero = z3.fpPlusZero(z3.Float32()) elif self._is_float64_sort(arg_sort): zero = z3.fpPlusZero(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isZero op case') temp = z3.fpEQ(arg, zero) self.visit(temp)
def prepare_float(val, signext=False, size=SIZE) -> z3.FPRef: if z3.is_fp(val): return val size_class = z3.Float64() if size == 32: size_class = z3.Float32() elif size == 128: size_class = z3.Float128() if type(val) in (int, float): result = z3.FPVal(val) else: bv_val = prepare(val, signext, size) result = z3.fpBVToFP(bv_val, size_class) return result
def gen_symbolic_args(func: 'instance.FunctionInstance'): symbolic_params = [] for i, e in enumerate(func.functype.args): if e == bin_format.i32: symbolic_params.append(z3.BitVec(f'i32_bv_{i}', 32)) elif e == bin_format.i64: symbolic_params.append(z3.BitVec(f'i64_bv_{i}', 64)) elif e == bin_format.f32: # f32_bv = z3.BitVec(f'f32_bv_{i}', 32) # symbolic_params.append(z3.fpBVToFP(f32_bv, z3.Float32())) # another approach symbolic_params.append(z3.FP(f'f32_{i}', z3.Float32())) else: # f64_bv = z3.BitVec(f'f64_bv_{i}', 64) # symbolic_params.append(z3.fpBVToFP(f64_bv, z3.Float64())) # another approach symbolic_params.append(z3.FP(f'f64_{i}', z3.Float64())) return symbolic_params
def gen_symbolic_args(func: 'instance.FunctionInstance'): symbolic_params = list() for i, e in enumerate(func.functype.args): if e == bin_format.i32: symbolic_params.append(z3.BitVec(f'i32_bv_{i}', 32)) elif e == bin_format.i64: symbolic_params.append(z3.BitVec(f'i64_bv_{i}', 64)) elif e == bin_format.f32: # The first approach is bit-vector based # f32_bv = z3.BitVec(f'f32_bv_{i}', 32) # symbolic_params.append(z3.fpBVToFP(f32_bv, z3.Float32())) # The second approach is float-point based symbolic_params.append(z3.FP(f'f32_{i}', z3.Float32())) else: # The first approach is bit-vector based # f64_bv = z3.BitVec(f'f64_bv_{i}', 64) # symbolic_params.append(z3.fpBVToFP(f64_bv, z3.Float64())) # The second approach is float-point based symbolic_params.append(z3.FP(f'f64_{i}', z3.Float64())) return symbolic_params
def _gen(expr_z3, symbolTable, cache, result): ###Leaf: var if _is_variable(expr_z3): if DEBUG: print "-- Branch _is_variable with ", expr_z3 symVar = expr_z3.decl().name() symVar = rename_var(symVar) if z3.is_int(expr_z3): symType = Sort.Int elif z3.is_fp(expr_z3): if expr_z3.sort() == z3.Float64(): symType = Sort.Float64 elif expr_z3.sort() == z3.Float32(): symType = Sort.Float32 else: raise NotImplementedError("Unexpected sort.", expr_z3.sort()) elif z3.is_real(expr_z3): symType = Sort.Float warnings.warn( "****WARNING****: Real variable '%s' treated as floating point" % symVar) else: raise NotImplementedError("Unexpected type for %s" % symbolName) if (symVar in symbolTable.keys()): assert symType == symbolTable[symVar] else: symbolTable[symVar] = symType if expr_z3.sort() == z3.Float32(): symVar = "TR32(%s)" % symVar # do the same ting for verify !!!!!!!! return symVar ###Leaf: val if _is_value(expr_z3): if DEBUG: print "-- Branch _is_value" if z3.is_fp(expr_z3) or z3.is_real(expr_z3): if DEBUG: print "---- Sub-Branch FP or Real" if isinstance(expr_z3, z3.FPNumRef): if DEBUG: print "------- Sub-Sub-Branch _is_FPNumRef" try: str_ret = str(sympy.Float(str(expr_z3), 17)) except ValueError: if expr_z3.isInf() and expr_z3.decl().kind( ) == z3.Z3_OP_FPA_PLUS_INF: str_ret = "INFINITY" elif expr_z3.isInf() and expr_z3.decl().kind( ) == z3.Z3_OP_FPA_MINUS_INF: str_ret = "- INFINITY" elif expr_z3.isNaN(): str_ret = "NAN" else: offset = 127 if expr_z3.sort() == z3.Float32( ) else 1023 #Z3 new version needs the offset to be taken into consideration expr_z3_exponent = expr_z3.exponent_as_long() - offset str_ret = str( sympy.Float((-1)**float(expr_z3.sign()) * float(str(expr_z3.significand())) * 2**(expr_z3_exponent), 17)) else: if DEBUG: print "------- Sub-Sub-Branch other than FPNumRef, probably FPRef" str_ret = str(sympy.Float(str((expr_z3)), 17)) elif z3.is_int(expr_z3): if DEBUG: print "---- Sub-Branch Integer" str_ret = str(sympy.Integer(str(expr_z3))) elif _is_true(expr_z3): str_ret = "0" elif _is_false(expr_z3): str_ret = "1" else: raise NotImplementedError( "[XSat: Coral Benchmarking] type not considered ") if expr_z3.sort() == z3.Float32(): str_ret = str_ret + "f" return str_ret #if (expr_z3 in cache): return cache[expr_z3] #cache will be a set of defined IDs #if (var_name(expr_z3) in cache): return cache[expr_z3] if (expr_z3.get_id() in cache): return var_name(expr_z3) cache.add(expr_z3.get_id()) #cache[expr_z3]=var_name(expr_z3) sort_z3 = expr_z3.decl().kind() expr_type = 'double' if expr_z3.sort() == z3.FPSort(8, 24): expr_type = 'float' ### if sort_z3 == z3.Z3_OP_FPA_LE: if DEBUG: print "-- Branch _is_le" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DLE(%s,%s); " \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) #########!!!!!!!!!!!! need to do something if sort_z3 == z3.Z3_OP_FPA_TO_FP: if DEBUG: print "-- Branch _is_fpFP" assert expr_z3.num_args() == 2 if not (_is_RNE(expr_z3.arg(0))): warnings.warn( "WARNING!!! I expect the first argument of fpFP is RNE, but it is ", expr_z3.arg(0)) x = _gen(expr_z3.arg(1), symbolTable, cache, result) if expr_z3.sort() == z3.FPSort(8, 24): x = "TR32(%s)" % x #else if expr_z3.sort()==z3.FPSort(8,24): # x = "TR(%s)" %x toAppend= "%s %s = %s; " \ %( expr_type, var_name(expr_z3), \ x,\ ) result.append(toAppend) return var_name(expr_z3) if sort_z3 == z3.Z3_OP_FPA_LT: if DEBUG: print "-- Branch _is_lt" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DLT(%s,%s);" \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_eq(expr_z3): if DEBUG: print "-- Branch _is_eq" lhs = _gen(expr_z3.arg(0), symbolTable, cache, result) rhs = _gen(expr_z3.arg(1), symbolTable, cache, result) toAppend= "double %s = DEQ(%s,%s);" \ %( var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpMul(expr_z3): if DEBUG: print "-- Branch _is_fpMul" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s*%s; " \ %( expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpDiv(expr_z3): if DEBUG: print "-- Branch _is_fpDiv" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s/%s; " \ %(expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpAdd(expr_z3): if DEBUG: print "-- Branch _is_fpAdd" if not _is_RNE(expr_z3.arg(0)): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) assert expr_z3.num_args() == 3 lhs = _gen(expr_z3.arg(1), symbolTable, cache, result) rhs = _gen(expr_z3.arg(2), symbolTable, cache, result) toAppend= "%s %s = %s+%s;" \ %( expr_type, var_name(expr_z3), \ lhs,\ rhs,\ ) result.append(toAppend) return var_name(expr_z3) if z3.is_and(expr_z3): if DEBUG: print "-- Branch _is_and" ##TODO Not sure if symbolTable will be treated in a multi-threaded way toAppendExpr = _gen(expr_z3.arg(0), symbolTable, cache, result) for i in range(1, expr_z3.num_args()): toAppendExpr = 'BAND( %s,%s )' % ( toAppendExpr, _gen(expr_z3.arg(i), symbolTable, cache, result)) toAppend= "double %s = %s; " \ %( var_name(expr_z3), \ toAppendExpr,\ ) result.append(toAppend) return var_name(expr_z3) if z3.is_not(expr_z3): if DEBUG: print "-- Branch _is_not" assert expr_z3.num_args() == 1 if not (expr_z3.arg(0).num_args() == 2): warnings.warn( "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ", expr_z3.arg(0)) op1 = _gen(expr_z3.arg(0).arg(0), symbolTable, cache, result) op2 = _gen(expr_z3.arg(0).arg(1), symbolTable, cache, result) if _is_ge(expr_z3.arg(0)): a = "DLT(%s,%s)" % (op1, op2) elif _is_gt(expr_z3.arg(0)): a = "DLE(%s,%s)" % (op1, op2) elif _is_le(expr_z3.arg(0)): a = "DGT(%s,%s)" % (op1, op2) elif _is_lt(expr_z3.arg(0)): a = "DGE(%s,%s)" % (op1, op2) elif _is_eq(expr_z3.arg(0)): a = "DNE(%s,%s)" % (op1, op2) elif _is_distinct(expr_z3.arg(0)): a = "DEQ(%s,%s)" % (op1, op2) else: raise NotImplementedError( "Not implemented case 004 for expr_z3 = %s. 'Not(or... )' is not handled yet" % expr_z3) toAppend= "%s %s = %s; " \ %( expr_type, var_name(expr_z3), \ a,\ ) result.append(toAppend) return var_name(expr_z3) if _is_fpNeg(expr_z3): if DEBUG: print "-- Branch _is_fpNeg" assert expr_z3.num_args() == 1 op1 = _gen(expr_z3.arg(0), symbolTable, cache, result) toAppend = "%s %s = - %s ;" \ %(expr_type, var_name(expr_z3), \ op1,\ ) result.append(toAppend) return var_name(expr_z3) raise NotImplementedError( "Not implemented case 002 for expr_z3 = %s, kind(%s)" % (expr_z3, expr_z3.decl().kind()))
def __add__(self, other): if isinstance(other, SymbolicSeq): return SymbolicSeq(self.z3var + other.z3var) else: return SymbolicSeq(self.z3var + other) def __eq__(self, other): if isinstance(other, SymbolicSeq): return z3.Eq(self.z3var, other.z3var) else: return NotImplemented _TYPE_TO_SMT_SORT = { int: z3.IntSort(), float: z3.Float64(), bool: z3.BoolSort(), str: z3.StringSort(), } def type_to_smt_sort(t: Type): if t in _TYPE_TO_SMT_SORT: return _TYPE_TO_SMT_SORT[t] origin = getattr(t, '__origin__', None) if origin in (List, Sequence, Container): item_type = t.__args__[0] return z3.SeqSort(type_to_smt_sort(item_type)) elif origin in (Dict, Mapping): key_type, val_type = t.__args__ return z3.ArraySort(type_to_smt_sort(key_type),
def f642i64(f: f64) -> i64: if utils.is_all_real(f): return struct.unpack('<q', struct.pack('<d', f))[0] return z3.fpToIEEEBV(f, z3.Float64())
def i642f64(i: i64) -> f64: if utils.is_all_real(i): i = int2i64(i) return struct.unpack('<i', struct.pack('<q', i))[0] return z3.fpToFP(i, z3.Float64())
from .esilclasses import * import z3 SIZE = 64 FSIZE = z3.Float64() ONE = z3.BitVecVal(1, SIZE) ZERO = z3.BitVecVal(0, SIZE) NEGONE = z3.BitVecVal(-1, SIZE) FONE = z3.FPVal(1.0, FSIZE) FZERO = z3.FPVal(0.0, FSIZE) FNEGONE = z3.FPVal(-1.0, FSIZE) INT = 1 FLOAT = 2 FPM = z3.RTZ() def pop_values(stack, state, num: int = 1, signext=False) -> List[z3.BitVecRef]: size = state.esil["size"] val_type = state.esil["type"] return [ get_value(stack.pop(), state, signext, size, val_type) for i in range(num) ]