def _attach_datatypes(self): self.Node, self.node_values = z3.EnumSort("Node", self.node_names) self.nodes = dict(zip(self.node_names, self.node_values)) # A datatype for storing a pair of edges self.Edge = z3.Datatype('Edge') self.Edge.declare('edge', ('node1', self.Node), ('node2', self.Node)) self.Edge = self.Edge.create() self.Nodeset = z3.ArraySort(self.Node, z3.BoolSort()) self.Edgeset = z3.ArraySort(self.Edge, z3.BoolSort()) self.Labelset = z3.ArraySort(z3.IntSort(), z3.BoolSort()) self.Labelmap = z3.ArraySort(self.Node, self.Labelset) # Graph, before a rule or action has applied. Merged Pregraph and Postgraph # into a single datatype. self.Graph = z3.Datatype('Graph') self.Graph.declare('graph', ('has', self.Nodeset), ('links', self.Edgeset), ('parents', self.Edgeset), ('labelmap', self.Labelmap)) self.Graph = self.Graph.create() # This represents a set of possible <pregraph, postgraph> pairs. self.Rule = z3.Datatype('Rule') self.Rule.declare('rule', ('pregraph', self.Graph), ('postgraph', self.Graph)) self.Rule = self.Rule.create()
def translate_type(self, ty): if ty == TINT: return z3.IntSort() if ty == TBOOL: return z3.BoolSort() if isinstance(ty, TARR): return z3.ArraySort(z3.IntSort(), self.translate_type(ty.ty))
def z3ArraySort(self, key, value): """Return the z3 ArraySort for the given key value.""" try: return self._z3ArraySorts[(askey(key), askey(value))] except KeyError: sort = z3.ArraySort(key, value) self._z3ArraySorts[(askey(key), askey(value))] = sort return sort
def type_to_z3sort(ast_typ: AstType) -> z3.SortRef: if isinstance(ast_typ, AstIntType): return IntSort() elif isinstance(ast_typ, AstBoolType): return BoolSort() else: # TODO: Multi-dimensional maps NYI assert isinstance(ast_typ, AstMapType) and len(ast_typ.domainT) == 1 return z3.ArraySort(type_to_z3sort(ast_typ.domainT[0]), type_to_z3sort(ast_typ.rangeT))
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), type_to_smt_sort(val_type)) return None
def _z3_sort(self, json_type, typeargs=[], typeargnames={}): # print "Looking up type %s (%s, %s): %s" % (json_type['name'], typeargs, typeargnames, json_type) ## Hard-coded Z3 correspondence for some types if json_type['name'] == 'nat': return z3.IntSort() if json_type['name'] == 'string': return z3.StringSort() if json_type['name'] == 'gmap': return z3.ArraySort(self._z3_sort(json_type['args'][0]), self._z3_sort(json_type['args'][1])) if json_type['what'] == 'type:var': t = typeargnames[json_type['name']] return self._z3_sort(t) if json_type['what'] == 'type:glob': if json_type['name'] == 'buf': return z3.SeqSort(z3.BitVecSort(8)) return self.z3_sort(json_type['name'], [ self._type_var_lookup(typeargnames, x) for x in json_type['args'] ]) if str(json_type) in self.json_to_sort: return self.json_to_sort[str(json_type)] if json_type['name'] == 'list': return z3.SeqSort(self._z3_sort(typeargs[0])) datatype = z3.Datatype(str(json_type['name'])) typeargnames = {} for i in range(0, len(typeargs)): typeargname = json_type['argnames'][i] typeargnames[typeargname] = typeargs[i] for c in json_type['constructors']: cname = str(c['name']) datatype.declare( cname, *[(cname + '_%d' % idx, self._z3_sort(argtype, [], typeargnames)) for (idx, argtype) in enumerate(c['argtypes'])]) t = datatype.create() self.json_to_sort[str(json_type)] = t return t
def mk_struct_sort(self, t): # Due to the sins of the fathers, struct arrays get passed through this # api too. Essentially, it's ``anything that contains a struct''. if t.type_id == esbmc.type.type_ids.struct: return self.mk_struct_sort2(t) else: subtype = esbmc.downcast_type(t.subtype) struct_sort = self.mk_struct_sort2(subtype) dom_width = self.calculate_array_domain_width(t) width_sort = z3.BitVecSort(dom_width, self.ctx) arr_sort = z3.ArraySort(width_sort, struct_sort.sort) result = Z3sort(arr_sort, esbmc.solve.smt_sort_kind.array, 1, dom_width) result.dom_sort = Z3sort(width_sort, esbmc.solve.smt_sort_kind.bv, dom_width) result.range_sort = struct_sort return result
def _type_to_z3(self, tp): """Convert a pySMT type into the corresponding Z3 sort.""" if tp.is_bool_type(): return self.z3BoolSort elif tp.is_real_type(): return self.z3RealSort elif tp.is_int_type(): return self.z3IntSort elif tp.is_array_type(): key_sort = self._type_to_z3(tp.index_type) val_sort = self._type_to_z3(tp.elem_type) try: return self.z3ArraySorts[(askey(key_sort), askey(val_sort))] except KeyError: sort = z3.ArraySort(key_sort, val_sort) self.z3ArraySorts[(askey(key_sort), askey(val_sort))] = sort return sort else: assert tp.is_bv_type(), "Unsupported type '%s'" % tp return self.z3BitVecSort(tp.width) raise NotImplementedError("Unsupported type in conversion: %s" % tp)
def mk_sort(self, args): kind = args[0] if kind == esbmc.solve.smt_sort_kind.bool: return Z3sort(z3.BoolSort(self.ctx), kind) elif kind == esbmc.solve.smt_sort_kind.bv: width = args[1] z3sort = z3.BitVecSort(width, self.ctx) return Z3sort(z3sort, kind, args[1]) elif kind == esbmc.solve.smt_sort_kind.array: domain = args[1] range_ = args[2] arr_sort = z3.ArraySort(domain.sort, range_.sort) range_width = range_.data_width if range_.data_width != 0 else 1 assert domain.data_width != 0 res_sort = Z3sort(arr_sort, kind, range_width, domain.data_width) res_sort.dom_sort = domain res_sort.range_sort = range_ return res_sort else: print kind assert False
def equal(self, x, val): cons_list = [] if isinstance(x, z3.ExprRef): if x.sort() == z3.ArraySort(z3.BitVecSort(32), z3.BitVecSort(8)): for i in range(len(val)): c_equal = z3.Concat(x[INT_SIZE * i + 3], x[INT_SIZE * i + 2], x[INT_SIZE * i + 1], x[INT_SIZE * i + 0]) \ == val[i] cons_list.append(c_equal) elif x.sort() == z3.RealSort(): c_equal = x == val cons_list.append(c_equal) else: raise err.Fatal('unhandled sort x: {}'.format(x.sort())) elif isinstance(x, list): cons_list = map((lambda x, c: x == c), x, val) else: raise err.Fatal('unhandled type: {}'.format(type(x))) # # loop sentinel # if cons_list == []: # cons_list = True return z3.And(cons_list)
def _parse_array_type(self, type_name): params = type_name[6:-1] # There may be parameterized views, so there may # be more than a comma in the typename comma_pos = 0 level = 0 for c in params: if c == ',' and level == 0: break if c == '{': level += 1 elif c == '}': level -= 1 comma_pos += 1 key_type = self._smt_sort(self.module.findSort(params[:comma_pos])) value_type = self._smt_sort( self.module.findSort(params[comma_pos + 1:])) return smt.ArraySort(key_type, value_type)
def ic2smt(self, ic, x): cons_list = [] if isinstance(x, z3.ExprRef): if x.sort() == z3.ArraySort(z3.BitVecSort(32), z3.BitVecSort(8)): for i in range(ic.dim): c_upper_bound = z3.Concat(x[INT_SIZE * i + 3], x[INT_SIZE * i + 2], x[INT_SIZE * i + 1], x[INT_SIZE * i + 0]) <= ic.h[i] c_lower_bound = z3.Concat(x[INT_SIZE * i + 3], x[INT_SIZE * i + 2], x[INT_SIZE * i + 1], x[INT_SIZE * i + 0]) >= ic.l[i] cons_list.append(c_upper_bound) cons_list.append(c_lower_bound) else: raise err.Fatal('unknown sort: {}'.format(x.sort())) elif isinstance(x, list): cons_list = map((lambda x, c: x <= c), x, ic.h)\ + map((lambda x, c: x >= c), x, ic.l) else: raise err.Fatal('unhandled type: {}'.format(type(x))) return z3.And(cons_list)
m = jc.get_module('Main') stateType = m.get_type("state") sym = json_sym.SymbolicJSON(jc) sym.register_base_type("positive", lambda args: z3.IntSort()) sym.register_base_type("string", lambda args: z3.StringSort()) # XXX u0 is a u64? and u1 is a u32... sym.register_base_type("u0", lambda args: z3.BitVecSort(64)) sym.register_base_type("u1", lambda args: z3.BitVecSort(32)) sym.register_base_type( "gmap", lambda args: z3.ArraySort( sym.z3_sort(args[0]), sym.z3_sort({ 'what': 'type:glob', 'name': 'option', 'args': [args[1]], 'mod': m, }))) sym.register_base_type("buf", lambda args: z3.SeqSort(z3.BitVecSort(8))) # sym.register_base_type("list", lambda args: z3.SeqSort(sym.z3_sort(args[0]))) # XXX hack: list is always of inode_state sym.register_base_type( "list", lambda args: z3.SeqSort( sym.z3_sort({ 'what': 'type:glob', 'name': 'inode_state', 'args': [], 'mod': m, }))) sym.register_base_type("fh", lambda args: z3.StringSort())
def as_z3(self): return z3.ArraySort(z3.IntSort(), self.element_type.as_z3())
def ArraySort(self, *args): return z3.ArraySort(*args)
import z3 from z3.z3 import _to_expr_ref import collections MemorySort = z3.ArraySort(z3.BitVecSort(256), z3.BitVecSort(8)) StorageSort = z3.ArraySort(z3.BitVecSort(256), z3.BitVecSort(256)) MemoryEmpty = z3.K(z3.BitVecSort(256), z3.BitVecVal(0, 8)) StorageEmpty = z3.K(z3.BitVecSort(256), z3.BitVecVal(0, 256)) from . import mem ContractState = collections.namedtuple('ContractState', 'code storage balance nonce') ContractState.__new__.__defaults__ = (None, None, None) def cached(fn): def wrapper(self, *args): if fn.__name__ not in self._cache: self._cache[fn.__name__] = fn(self, *args) return self._cache[fn.__name__] return wrapper def storage_empty_policy(name, addr): return StorageEmpty def storage_any_policy(name, addr):