def totalAgreement(inputOutputPair, gene, aVars, rVars, expressionValues, counter): inputName0 = inputOutputPair[0] inputName1 = inputOutputPair[1] inputName2 = inputOutputPair[2] outputName = inputOutputPair[3] input0 = expressionValues.loc[inputName0, :] input1 = expressionValues.loc[inputName1, :] input2 = expressionValues.loc[inputName2, :] input = [ modeCalc([input0[i], input1[i], input2[i]]) for i in range(len(input0)) ] output = expressionValues.loc[outputName, :] #counter += 1 score = makeEnforcedVar("counter_%i" % counter) (encoding, match) = circuitEvaluatesTo(gene, aVars, rVars, input, output, counter) return (z3.And( encoding, z3.If(match, score == z3.BitVecVal(1, 32), score == z3.BitVecVal(0, 32))), score)
def start_path_group(memory_dump, start_ip, avoid=None): """ Parse a memory dump, construct a base state, and return a PathGroup. """ mem = parse_mc_memory_dump(memory_dump) cpu = CPU() cpu.registers[Register.R0] = z3.BitVecVal(start_ip, 16) path = Path() inp = IO(IOKind.INPUT, []) out = IO(IOKind.OUTPUT, []) entry_state = State(cpu, mem, path, inp, out, False) pg = PathGroup([entry_state], avoid=avoid) return pg
def declare_global_constant(self, ctx, name, global_type, value=None, value_type=None): ctx['globals'][name] = dt.fresh_ptr(ctx, name, global_type) if value_type.is_array() and value_type.deref().is_int(): inner_size = value_type.deref().size() for n, i in enumerate(util.parse_constant_array(value)): ctx['globals'][name].getelementptr( ctx, util.i64(0), util.i64(n)).write(ctx, z3.BitVecVal(i, inner_size))
def _try_build_reduced_array(self, index_min, index_max): if self._z3obj is not None: # symbolic mode return self._z3obj if index_max - index_min >= 2**self.index_width: return self.z3obj res = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) for i in range(index_min, index_max + 1): if i in self._conc_store: res = z3.Store(res, z3.BitVecVal(i, self.index_width), self._conc_store[i].z3obj) return res
def value(self): return simplify( z3.Concat( self.ppn, z3.BitVecVal(0, 2), resize(self.d, 1), resize(self.a, 1), resize(self.g, 1), resize(self.u, 1), resize(self.x, 1), resize(self.w, 1), resize(self.r, 1), resize(self.v, 1), ))
def update_storages(self, sstore_data): for address, index, value in sstore_data: address = int(address[2:], 16) assert address in self.root_wstate.address_to_account if index > 100: if index in self.log_sha_to_sym_sha: store_index = self.log_sha_to_sym_sha[index] else: log_shas = list(self.log_sha_to_sym_sha.keys()) diffs = [abs(l - index) for l in log_shas] min_index = diffs.index(min(diffs)) diff = diffs[min_index] if diff < 10: relative_index = log_shas[min_index] store_index = z3.simplify(self.log_sha_to_sym_sha[relative_index] + z3.BitVecVal(diff, 256)) self.log_sha_to_sym_sha[index] = store_index else: store_index = z3.BitVecVal(index, 256) else: store_index = z3.BitVecVal(index, 256) store_value = self.log_sha_to_sym_sha.get(value, z3.BitVecVal(value, 256)) account = self.root_wstate.address_to_account[address] account.storage.store(store_index, store_value)
def check_interp(interp, constraints, bits=32, valbits=8): """Checks that a list of @constraints (addr, value) (as python ints) match a z3 FuncInterp (@interp). """ constraints = dict((addr, z3.BitVecVal(val, valbits)) for addr, val in constraints) l = interp.as_list() for entry in l: if not isinstance(entry, list) or len(entry) < 2: continue addr, value = entry[0], entry[1] if addr.as_long() in constraints: assert equiv(value, constraints[addr.as_long()])
def sys_reclaim_vector(old, vector): pid = old.vectors[vector].owner cond = z3.And( is_pid_valid(pid), old.procs[pid].state == dt.proc_state.PROC_ZOMBIE, old.procs[pid].nr_intremaps() == 0, ) new = old.copy() new.vectors[vector].owner = z3.BitVecVal(0, dt.pid_t) new.procs[pid].nr_vectors[vector] -= 1 return cond, util.If(cond, new, old)
def z3_cast(val, to_type): # FIXME: Unify to_type properly # some checks to guarantee that the inputs are usable if isinstance(val, (z3.BoolSortRef, z3.BoolRef)): # Convert boolean variables to a bit vector representation # TODO: Streamline bools and their evaluation val = z3.If(val, z3.BitVecVal(1, 1), z3.BitVecVal(0, 1)) if isinstance(to_type, (z3.BoolSortRef, z3.BoolRef)): # casting to a bool is simple, just check if the value is equal to 1 # this works for bitvectors and integers, we convert any bools before # if val is not a single bit vector, this will (intentionally) fail return val == z3.BitVecVal(1, 1) # from here on we assume we are working with integer or bitvector types if isinstance(to_type, (z3.BitVecSortRef, z3.BitVecRef)): # It can happen that we get a bitvector type as target, get its size. to_type_size = to_type.size() elif not isinstance(to_type, int) and to_type == z3.IntSort(): return val.as_long() else: to_type_size = to_type if isinstance(val, int): # It can happen that we get an int, cast it to a bit vector. return z3.BitVecVal(val, to_type_size) # preprocessing done, the actual casting starts here val_size = val.size() if val_size < to_type_size: # the target value is larger, extend with zeros return z3.ZeroExt(to_type_size - val_size, val) elif val_size > to_type_size: # the target value is smaller, truncate everything on the right return z3.Extract(to_type_size - 1, 0, val) else: # nothing to do return val
def free_page_table_page(old, frm, index, to, from_type, to_type): cond = z3.And( # The frm pn has the correct type and owned by current is_pn_valid(frm), old.pages[frm].type == from_type, old.pages[frm].owner == old.current, # Index is a valid page index z3.ULT(index, 512), # The to pn has the correct type and owned by current is_pn_valid(to), old.pages[to].type == to_type, old.pages[to].owner == old.current, # index does have the P bit in the from page old.pages[frm].data(index) & dt.PTE_P != 0, # The current pgtable entry matches to... z3.Extract(63, 40, z3.UDiv(old.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + to) == z3.BitVecVal(0, 24), z3.Extract(39, 0, z3.UDiv(old.pages_ptr_to_int, util.i64( dt.PAGE_SIZE)) + to) == z3.Extract(51, 12, old.pages[frm].data(index)), ) new = old.copy() new.pages[frm].data[index] = util.i64(0) new.pages[to].owner = z3.BitVecVal(0, dt.pid_t) new.pages[to].type = dt.page_type.PAGE_TYPE_FREE new.procs[old.current].nr_pages[to] -= 1 new.flush_tlb(old.current) return cond, util.If(cond, new, old)
def __eq__(self, other: Union[int, "BitVec"]) -> Bool: # type: ignore """Create an equality expression. :param other: The int or BitVec to compare to this BitVecFunc :return: The resulting Bool """ if not isinstance(other, BitVec): other = BitVec(z3.BitVecVal(other, self.size())) return _comparison_helper(self, other, operator.eq, default_value=False, inputs_equal=True)
def If(a: Union[Bool, bool], b: Union[BitVec, int], c: Union[BitVec, int]) -> BitVec: """Create an if-then-else expression. :param a: :param b: :param c: :return: """ # TODO: Handle BitVecFunc if not isinstance(a, Bool): a = Bool(z3.BoolVal(a)) if not isinstance(b, BitVec): b = BitVec(z3.BitVecVal(b, 256)) if not isinstance(c, BitVec): c = BitVec(z3.BitVecVal(c, 256)) union = a.annotations.union(b.annotations).union(c.annotations) bvf = [] # type: List[BitVecFunc] if isinstance(a, BitVecFunc): bvf += [a] if isinstance(b, BitVecFunc): bvf += [b] if isinstance(c, BitVecFunc): bvf += [c] if bvf: raw = z3.If(a.raw, b.raw, c.raw) nested_functions = [ nf for func in bvf for nf in func.nested_functions ] + bvf return BitVecFunc(raw, func_name="Hybrid", nested_functions=nested_functions) return BitVec(z3.If(a.raw, b.raw, c.raw), union)
def opcode_get_memory(memory, offset, length=32): parts = [] if not is_z3_express(length): for i in range(format_to_int(length)): index = opcode_add(offset, i) parts.append(memory[index]) return z3.simplify(z3.Concat(parts)) # delete tail zero for i in range(opcode_memory.LENGTH): check_get_express = z3.And(i >= offset, i < offset + length) parts.append(z3.If(check_get_express, memory[i], z3.BitVecVal(0, 8))) return z3.simplify(z3.Concat(parts))
def z3obj(self): if self._z3obj is not None: # symbolic mode return self._z3obj # concrete mode if self._z3objConcCache is not None: return self._z3objConcCache res = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) for index in self._conc_store: res = z3.Store(res, z3.BitVecVal(index, self.index_width), self._conc_store[index].z3obj) self._z3objConcCache = res return res
def to_z3(self, val, strict=False): if val in self.map: return self.map[val] if val not in self.domain and val is not None: if strict: raise exception.PolicyRuntimeException( "Z3 Finite type: {} is not a value of {}".format( val, self.name)) else: val = '__OTHER__' code = len(self.map) bvect = z3.BitVecVal(code, self.type_instance) self.map[val] = bvect self.back[code] = val return bvect
def _to_smt_constant_expression(expr_object, smt_context_object): val_obj = expr_object.value_object constant_type = val_obj.value_type if (constant_type.type_code == exprtypes.TypeCodes.boolean_type): return z3.BoolVal(val_obj.value_object, smt_context_object.ctx()) elif (constant_type.type_code == exprtypes.TypeCodes.integer_type): return z3.IntVal(val_obj.value_object, smt_context_object.ctx()) elif (constant_type.type_code == exprtypes.TypeCodes.bit_vector_type): int_value = val_obj.value_object.value return z3.BitVecVal(int_value, constant_type.size, smt_context_object.ctx()) elif (constant_type.type_code == exprtypes.TypeCodes.string_type): return z3.StringVal(val_obj.value_object, smt_context_object.ctx()) else: raise basetypes.UnhandledCaseError('Odd type code: %s' % constant_type.type_code)
def opcode_init_call_data(calldata, init_data): if init_data[:2] == '0x': init_data = init_data[2:] length = len(init_data) / 2 low = 0 high = low + 2 for i in range(length): data = int(init_data[low:high], 16) calldata = z3.Store(calldata, i, z3.BitVecVal(data, 8)) low += 2 high = low + 2 return z3.simplify(calldata)
def register_define(context, n, s, f, bit_is_set): """Register and define one comparison to constant :param context: z3 context to create predicate and rules :param n: the constant :param s: the size of domain :param f: the predicate implementing the comparison :param bit_is_set: when we check a bit, add a rule if set or not depending on the truth of this arg. This is the way we handle < and > in a single function. """ context.register_relation(f) sort = f.domain(0) var = z3.Const('X', sort) glob_mask = (1 << s) - 1 for p in range(s): bit = 1 << p if (n & bit != 0) == bit_is_set: mask = glob_mask ^ (bit - 1) prefix = (n & mask) ^ bit z3_prefix = z3.BitVecVal(prefix, sort) z3_mask = z3.BitVecVal(mask, sort) equation = z3_prefix == (var & z3_mask) context.rule(z3.ForAll([var], z3.Implies(equation, f(var))))
def calculate(solver, xs): MOD_BASE = z3.BitVecVal(36, 8) solver.add(((xs[0] + xs[1]) % MOD_BASE) == 14) solver.add(((xs[2] + xs[3]) % MOD_BASE) == 24) solver.add(((xs[2] - xs[0]) % MOD_BASE) == 6) solver.add(((xs[1] + xs[3] + xs[5]) % MOD_BASE) == 4) solver.add(((xs[2] + xs[4] + xs[6]) % MOD_BASE) == 13) solver.add(((xs[3] + xs[4] + xs[5]) % MOD_BASE) == 22) solver.add(((xs[6] + xs[8] + xs[10]) % MOD_BASE) == 31) solver.add(((xs[1] + xs[4] + xs[7]) % MOD_BASE) == 7) solver.add(((xs[9] + xs[12] + xs[15]) % MOD_BASE) == 20) solver.add(((xs[13] + xs[14] + xs[15]) % MOD_BASE) == 12) solver.add(((xs[8] + xs[9] + xs[10]) % MOD_BASE) == 27) solver.add(((xs[7] + xs[12] + xs[13]) % MOD_BASE) == 23)
class TestBoolType(base.TestCase): """Z3 Boolean values""" bool_false = z3.BitVecVal(0, 1) bool_true = z3.BitVecVal(1, 1) def setUp(self): self.type = primitives.BoolType() super(TestBoolType, self).setUp() def test_marshal(self): self.assertEqual('True', self.type.marshall(True)) self.assertEqual('False', self.type.marshall(False)) def test_unmarshal(self): self.assertEqual(True, self.type.unmarshall('True')) self.assertEqual(False, self.type.unmarshall('False')) def test_to_z3(self): self.assertEqual(TestBoolType.bool_true, self.type.to_z3(True)) self.assertEqual(TestBoolType.bool_false, self.type.to_z3(False)) def test_from_z3(self): self.assertEqual(True, TestBoolType.bool_true) self.assertEqual(False, TestBoolType.bool_false)
def getOperands(self, ops, concat=True): rops = [] for op in ops: if (op.isVar()): if (op.size > 1): rops.append( z3.Concat( map(lambda b: z3.BitVec(b, 8), op.get_bytes()))) else: rops.append(z3.BitVec(op.get_bytes()[0], 8)) else: rops.append(z3.BitVecVal(op.getValue(), 8 * op.size)) return rops
def __new_constant__(self, constant, code: int): """ :param constant: bool | int | float :param code: :return: """ if isinstance(constant, bool): return z3.BoolVal(constant) elif isinstance(constant, int): if code == self.__s_code__: return z3.BitVecVal(constant, self.longLength) else: return z3.IntVal(constant) else: return z3.RealVal(constant)
def sv32(options, asid, ppn): return VMMode( options, mode=z3.BitVecVal(1, 1), asid=asid, ppn=ppn, pa_size=34, page_size=4096, pte_size=4, levels=2, vpn_bits=[(21, 12), (31, 22)], ppn_bits=[(19, 10), (31, 20)], f_satp=satp32, f_pte=pte32, )
def sv48(options, asid, ppn): return VMMode( options, mode=z3.BitVecVal(9, 4), asid=asid, ppn=ppn, pa_size=56, page_size=4096, pte_size=8, levels=3, vpn_bits=[(20, 12), (29, 21), (38, 30), (47, 39)], ppn_bits=[(18, 10), (27, 19), (36, 28), (53, 37)], f_satp=satp64(9), f_pte=pte64, )
def bare64(options): return VMMode( options, mode=z3.BitVecVal(0, 4), asid=0, ppn=0, pa_size=34, page_size=None, pte_size=None, levels=None, vpn_bits=[], ppn_bits=[], f_satp=satp64, f_pte=None, )
def spec_lemma_nr_fds_refcnt(kernelstate): conj = [] pid = util.FreshBitVec('pid', dt.pid_t) fd = util.FreshBitVec('fd', dt.fd_t) # unused procs do not have any fds. # valid(pid) & state(pid)== PROC_UNUSED ==> pid.nr_fds == 0 conj.append( z3.ForAll( [pid], z3.Implies( is_pid_valid(pid), z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, kernelstate.procs[pid].nr_fds() == z3.BitVecVal( 0, dt.size_t))))) # unused procs do not have any opened files # valid(pid) & valid(fd) & state(pid) == PROC_UNUSED ==> !valid(openedfile(pid, fd)) conj.append( z3.ForAll( [pid, fd], z3.Implies( z3.And(is_pid_valid(pid), is_fd_valid(fd)), z3.Implies( kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED, z3.Not(is_fn_valid(kernelstate.procs[pid].ofile(fd))))))) # a procs have opened a file, the state of this procs must not be UNUSED # valid(pid) & valid(fd) & valid(fn) ==> state(pid) != PROC_UNUSED conj.append( z3.ForAll( [pid, fd], z3.Implies( z3.And(is_pid_valid(pid), is_fd_valid(fd), is_fn_valid(kernelstate.procs[pid].ofile(fd))), kernelstate.procs[pid].state != dt.proc_state.PROC_UNUSED))) # Correctness definition for `permutation` based refcount kernelstate.procs.nr_fds.check( conj, is_owner_valid=is_pid_valid, is_owned_valid=is_fd_valid, max_refs=dt.NOFILE, ownedby=lambda pid, fd: is_fn_valid(kernelstate.procs[pid].ofile(fd))) return z3.And(*conj)
def _get_register(self, reg): """Get the current value of the specified register""" reg = canonical_register(reg) if reg == canonical_register("zero"): return resize(0, self._options.xlen) try: r = self._registers[reg] return r except KeyError: if self._options.arbitrary_initial_values: init = z3.BitVec(f"_{self.name}_{reg}_init", self._options.xlen) else: init = z3.BitVecVal(0, self._options.xlen) return self._registers.setdefault(reg, init)
def _switch_to_symbolic(self): if self._conc_store is not None: assert self._z3obj is None self._z3obj = z3.Array ( self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width) ) for index in self._conc_store: self._z3obj = z3.Store ( self._z3obj, z3.BitVecVal(index, self.index_width), self._conc_store[index].z3obj ) self._conc_store = None
def srem(self, ctx, return_type, a, atype, b, btype, nuw=False, nsw=False, exact=False): assert atype == return_type assert atype == btype assert not nuw and not nsw and not exact assert util.path_condition_implies( ctx, b != z3.BitVecVal(0, btype.size())), "srem by zero" return z3.SRem(a, b)
def blank_state(self, addr: Address = 0) -> ESILState: """ Create an ESILState with everything (except PC) symbolic :param addr: Name of function or address to begin execution """ addr = self.r2api.get_address(addr) self.state_manager = ESILStateManager([], lazy=self.lazy) options = self.options.copy() options["sym"] = True state = self.state_manager.entry_state(self.r2api, **options) pc_size = state.registers["PC"].size() state.registers["PC"] = z3.BitVecVal(addr, pc_size) return state