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 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 smt_var(typ: Type, name: str): z3type = type_to_smt_sort(typ) if z3type is None: if getattr(typ, '__origin__', None) is Tuple: if len(typ.__args__) == 2 and typ.__args__[1] == ...: z3type = z3.SeqSort(type_to_smt_sort(typ.__args__[0])) else: return tuple( smt_var(t, name + str(idx)) for (idx, t) in enumerate(typ.__args__)) var = z3.Const(name, z3type) if isinstance(z3type, z3.SeqSortRef): var = SymbolicSeq(var) return var
def setupProblem(self): self.stackvars = {} self.Qf = z3.Function("final", z3.SeqSort(z3.IntSort()), z3.BoolSort()) self.d = z3.Function("delta", z3.SeqSort(z3.IntSort()), z3.StringSort(), z3.SeqSort(z3.IntSort())) for (w, st, final, has_children) in self.t.iter(): sv = b"stack" + base64.b16encode(w) self.stackvars[w] = Sequence(sv) self.s_add_finalstate(w, final) if final and has_children: self.s_add_nonemptystate(w) if len(w): self.s_add_transition_to(w) self.s.add(self.stackvars[b''] == z3.Unit(z3.IntVal(0))) # most useful convention: # accept by drained stack, but don't read any more and fail then self.s.add(self.Qf(z3.Empty(z3.SeqSort(z3.IntSort()))) == True)
def construct_from_z3_model(self, m, d, Qf, alphabet): to_check = [0] checked = set(to_check) print("Extracting tables") self.D = dict() self.QF = set() self.productive = None print("m[d] = %s" % m[d]) print("m[qf] = %s" % m[Qf]) symbols = set([0]) while len(to_check): current = to_check.pop() conf = z3.Unit(z3.IntVal(current)) for a in alphabet: # range(0, 256): y = m.evaluate( d( # z3.SubSeq(conf, z3.Length(conf)-1, 1), conf, z3.StringVal(bytes([a]))), model_completion=True) def extract_seq_as_list(y): result = List() for c in y.children(): if isinstance(c, z3.SeqRef): result += extract_seq_as_list(c) else: result += List([c.as_long()]) return result rhs = extract_seq_as_list(y) for symbol in rhs: symbols.add(symbol) Dq = self.D.setdefault(current, dict()) Dq[a] = rhs for i in rhs: if not i in checked: checked.add(i) to_check += [i] if m.evaluate(Qf(z3.Empty(z3.SeqSort(z3.IntSort())))): self.QF.add(List([])) print("(stack/q) symbols encountered: %s" % symbols) for symbol in symbols: conf = z3.Unit(z3.IntVal(symbol)) f = m.evaluate(Qf(conf)) if f: self.QF.add(List([symbol])) self.symbols = symbols
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()) ### Fix later sym.register_base_type("fileid", lambda args: z3.BitVecSort(64)) sym.register_base_type("createverf", lambda args: z3.BitVecSort(64))