def attempt_exploit(results, ctx): c = CombinedSymbolicResult() for r in results[::-1]: c.prepend(r) c.combine(ctx.initial_storage, ctx.initial_balance) c.simplify() extra_constraints = get_exploit_constraints(c, ctx) for res in c.results: expr = None for controlled_addr in ctx.controlled_addrs: new_caller = z3.Extract(159, 0, z3.BitVec('CALLER_%d' % res.xid, 256)) == controlled_addr if expr is None: expr = new_caller else: expr = z3.Or(expr, new_caller) extra_constraints.append(expr) try: model = check_model_and_resolve(c.constraints + extra_constraints, c.sha_constraints) # enforce we control all CALLER-addresses if any(model[v].as_long() not in ctx.controlled_addrs for v in model if v.name().startswith('CALLER')): raise InfeasibleExploit return model_to_calls(model, c.idx_dict), c, model except IntractablePath: raise InfeasibleExploit
def control_address_constraints(sym_addr, controlled_addrs): sub_exprs = [ sym_addr == controlled_addr for controlled_addr in controlled_addrs ] expr = sub_exprs[0] for sub_expr in sub_exprs[1:]: expr = z3.Or(expr, sub_expr) return expr
def addTickSMT(self): for each in self.newClocks: self.tickDict["t_%s" % (each)] = z3.Function( "t_%s" % (each), z3.IntSort(), z3.BoolSort()) tick = self.tickDict["t_%s" % (each)] if self.bound > 0: y = z3.Int("y") if self.period > 0: for y in range(1, self.bound + 1): self.solver.add( z3.Implies( y >= self.k, tick((y - self.l) % self.p + self.l) == tick(y))) # self.solver.add( # z3.ForAll(y,z3.Implies( # z3.And(y >= self.k,y <= self.bound), # tick((y - self.l) % self.p + self.l) == tick(y)))) elif self.bound == 0: x = z3.Int("x") if self.period > 0: y = z3.Int("y") self.solver.add( z3.ForAll( y, z3.Implies( y >= self.k, tick((y - self.l) % self.p + self.l) == tick(y)))) clockListTmp = [] x = z3.Int("x") for each in self.tickDict.keys(): tick = self.tickDict[each] clockListTmp.append(tick(x)) if self.bound == 0: self.solver.add( z3.ForAll(x, z3.Implies(x >= 1, z3.Or(clockListTmp)))) else: for i in range(1, self.bound + 1): tmp = [] for tick in self.tickDict.values(): tmp.append(tick(i)) self.solver.add(z3.Or(tmp))
def __init__(self, choice_blocks): # Define the choice blocks contained by this construct. self.choice_blocks = choice_blocks # Which lock requests are present within the child blocks? self.lock_requests = set([]) # Do we require to lock certain variables? self.render_acquire_locks = False # If so, which lock request phases do we have, and what are the lock ranges that need to be acquired? self.lock_request_phases = [] self.lock_ranges = [] # In case of no else, locks have to be released. self.render_release_locks = False # Up to which lock entry in the lock list do we need to release? self.release_up_to_lock = 0 # What is the resulting encapsulating guard expression? self.guard_expressions = set([]) self.guard_statements = set([]) for block in choice_blocks: self.lock_requests.update(block.lock_requests) if block.__class__.__name__ == "TransitionBlock": self.guard_expressions.add(block.guard_expression) self.guard_statements.add(block.guard_statement) else: self.guard_expressions |= block.guard_expressions self.guard_statements |= block.guard_statements # Does the combination of all the guards always evaluate to true? If so, we can use an else statement. self.close_with_else = False encapsulating_guard_expression = z3.Or( [e.z3py_expression for e in self.guard_expressions]) if len(self.guard_expressions) > 0 and z3_check_trivially_satisfiable( encapsulating_guard_expression): self.close_with_else = True # Disable the guards of child transition blocks. for block in choice_blocks: if block.__class__.__name__ == "TransitionBlock": block.encompass_transition_guard(False) elif block.__class__.__name__ == "NonDeterministicBlock": # Note that we might have multiple statements with the same guard in a nested non deterministic block. # TODO ensure that guard expressions are only removed when safe! for nested_block in block.choice_blocks: if nested_block.__class__.__name__ == "TransitionBlock": # The transition doesn't need a guard if the encompassing guard only contains one element. nested_block.encompass_transition_guard( len(block.guard_expressions) > 1)
def addExtraConstraints(self): model = self.solver.model() ExtraConstraints = [] # if len(self.printParameter.keys()) == 0: # for each in self.newClocks: # self.tickDict["t_%s" % (each)] = z3.Function("t_%s" % (each), z3.IntSort(), z3.BoolSort()) # for i in range(1, self.bound + 1): # tmp = self.tickDict["t_%s" % (each)] # ExtraConstraints.append(tmp(i) != model.eval(tmp(i))) for each in self.printParameter.keys(): ExtraConstraints.append(self.printParameter[each] != model.eval( self.printParameter[each])) self.solver.add(z3.Or(ExtraConstraints))
def gen_model(solver, X): '''Given a Z3 solver instance and set of variables X, return single set of value assignments if SAT.''' if solver.check() == z3.sat: # Satisfiable model = solver.model() # Gen model if len(model) == 0: print( 'SAT, but no values returned. Typically occurs when 0 constraints are passed to Z3.' ) return None counter_c = z3.Or([x != model[x] for x in X]) # Add counter constraint solver.add(counter_c) return model return None
def check_kills(f_pos, f_neg, mutants, test, aps): """ Checks which mutants out of a given list get killed by a given test. """ cnf = stl_model_to_cnf(test, aps) s = z3.Solver() count = 1 # Initialized with 1 due to mutant that was used to generate test for i in range(0, len(mutants)): m = mutants[i] if m.killed: continue s.push() s.add( z3.Or(z3.And(f_pos, z3.And(cnf), m.z3_neg), z3.And(f_neg, m.z3_pos, z3.And(cnf)))) if s.check() == z3.sat: mutants[i].killed = True count += 1 s.pop() return count
def does_test_kill(original_pos, original_neg, formula_pos, formula_neg, test, cons): """ Checks whether the given test kills the given formula. Args: original_pos (z3 instance) : Positive encoded temporal logic formula for which test was generated. original_neg (z3 instance) : Negative encoded temporal logic formula for which test was generated. formula_pos (z3 instance) : Positive encoded temporal logic formula that is checked against the given test. formula_neg (z3 instance) : Negative encoded temporal logic formula that is checked against the given test. test (z3 model) : Test signal that either does or does not kill the given formula. cons (list) : z3 instances of constants used in test and formula. Returns: bool : True if test kills the given formula, else false. """ s = z3.Solver() s.add( z3.Or( z3.And(original_pos, z3.And(stl_model_to_cnf(test, cons)), formula_neg), z3.And(original_neg, formula_pos, z3.And(stl_model_to_cnf(test, cons))))) return True if s.check() == z3.sat else False
def run_symbolic(program, path, code=None, state=None, ctx=None, inclusive=False): MAX_CALLDATA_SIZE = 256 xid = gen_exec_id() state = state or SymbolicEVMState(xid=xid, code=code) storage = state.storage constraints = [] sha_constraints = dict() ctx = ctx or dict() min_timestamp = (datetime.datetime.now() - datetime.datetime(1970, 1, 1)).total_seconds() # make sure we can exploit it in the foreseable future max_timestamp = (datetime.datetime(2020, 1, 1) - datetime.datetime(1970, 1, 1)).total_seconds() ctx['CODESIZE-ADDRESS'] = len(code) calldata = z3.Array('CALLDATA_%d' % xid, z3.BitVecSort(256), z3.BitVecSort(8)) calldatasize = z3.BitVec('CALLDATASIZE_%d' % xid, 256) calldata_accesses = [0] instruction_count = 0 state.balance += ctx_or_symbolic('CALLVALUE', ctx, xid) target_op = program[path[-1]].name while state.pc in program: state.trace.append(state.pc) instruction_count += 1 # have we reached the end of our path? if ((inclusive and len(path) == 0) or (not inclusive and path == [state.pc])): state.success = True constraints.append( z3.Or(*(z3.ULE(calldatasize, access) for access in calldata_accesses))) return SymbolicResult(xid, state, constraints, sha_constraints, target_op) # if not, have we reached another step of our path? elif state.pc == path[0]: path = path[1:] ins = program[state.pc] opcode = ins.op op = ins.name stk = state.stack mem = state.memory state.gas -= ins.gas # Valid operations # Pushes first because they are very frequent if 0x60 <= opcode <= 0x7f: stk.append(int.from_bytes(ins.arg, byteorder='big')) state.pc += opcode - 0x5f # Move 1 byte forward for 0x60, up to 32 bytes for 0x7f # Arithmetic elif opcode < 0x10: if op == 'STOP': if path: raise IntractablePath(state.trace, path) state.success = True constraints.append( z3.Or(*(z3.ULE(calldatasize, access) for access in calldata_accesses))) return SymbolicResult(xid, state, constraints, sha_constraints, target_op) elif op == 'ADD': stk.append(stk.pop() + stk.pop()) elif op == 'SUB': stk.append(stk.pop() - stk.pop()) elif op == 'MUL': stk.append(stk.pop() * stk.pop()) elif op == 'DIV': s0, s1 = stk.pop(), stk.pop() if concrete(s1): stk.append(0 if s1 == 0 else s0 / s1 if concrete(s0) else z3.UDiv(s0, s1)) else: stk.append( z3.If(s1 == 0, z3.BitVecVal(0, 256), z3.UDiv(s0, s1))) elif op == 'MOD': s0, s1 = stk.pop(), stk.pop() if concrete(s1): stk.append(0 if s1 == 0 else s0 % s1) else: stk.append( z3.If(s1 == 0, z3.BitVecVal(0, 256), z3.URem(s0, s1))) elif op == 'SDIV': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): s0, s1 = teether.util.utils.to_signed( s0), teether.util.utils.to_signed(s1) stk.append(0 if s1 == 0 else abs(s0) // abs(s1) * (-1 if s0 * s1 < 0 else 1)) elif concrete(s1): stk.append(0 if s1 == 0 else s0 / s1) else: stk.append(z3.If(s1 == 0, z3.BitVecVal(0, 256), s0 / s1)) elif op == 'SMOD': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): s0, s1 = teether.util.utils.to_signed( s0), teether.util.utils.to_signed(s1) stk.append(0 if s1 == 0 else abs(s0) % abs(s1) * (-1 if s0 < 0 else 1)) elif concrete(s1): stk.append(0 if s1 == 0 else z3.SRem(s0, s1)) else: stk.append( z3.If(s1 == 0, z3.BitVecVal(0, 256), z3.SRem(s0, s1))) elif op == 'ADDMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() if concrete(s2): stk.append((s0 + s1) % s2 if s2 else 0) else: stk.append( z3.If(s2 == 0, z3.BitVecVal(0, 256), z3.URem((s0 + s1), s2))) elif op == 'MULMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() if concrete(s2): stk.append((s0 * s1) % s2 if s2 else 0) else: stk.append( z3.If(s2 == 0, z3.BitVecVal(0, 256), z3.URem((s0 * s1), s2))) elif op == 'EXP': base, exponent = stk.pop(), stk.pop() if concrete(base) and concrete(exponent): stk.append(pow(base, exponent, teether.util.utils.TT256)) else: if concrete(base) and teether.util.utils.is_pow2(base): l2 = teether.util.utils.log2(base) stk.append(1 << (l2 * exponent)) else: raise SymbolicError( 'exponentiation with symbolic exponent currently not supported :-/' ) elif op == 'SIGNEXTEND': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): if s0 <= 31: testbit = s0 * 8 + 7 if s1 & (1 << testbit): stk.append(s1 | (teether.util.utils.TT256 - (1 << testbit))) else: stk.append(s1 & ((1 << testbit) - 1)) else: stk.append(s1) elif concrete(s0): if s0 <= 31: oldwidth = (s0 + 1) * 8 stk.append(z3.SignExt(256 - oldwidth, s1)) else: stk.append(s1) else: raise SymbolicError( 'symbolic bitwidth for signextension is currently not supported' ) # Comparisons elif opcode < 0x20: if op == 'LT': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): stk.append(1 if s0 < s1 else 0) else: stk.append( z3.If(z3.ULT(s0, s1), z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'GT': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): stk.append(1 if s0 > s1 else 0) else: stk.append( z3.If(z3.UGT(s0, s1), z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'SLT': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): s0, s1 = teether.util.utils.to_signed( s0), teether.util.utils.to_signed(s1) stk.append(1 if s0 < s1 else 0) else: stk.append( z3.If(s0 < s1, z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'SGT': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): s0, s1 = teether.util.utils.to_signed( s0), teether.util.utils.to_signed(s1) stk.append(1 if s0 > s1 else 0) else: stk.append( z3.If(s0 > s1, z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'EQ': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): stk.append(1 if s0 == s1 else 0) else: stk.append( z3.If(s0 == s1, z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'ISZERO': s0 = stk.pop() if concrete(s0): stk.append(1 if s0 == 0 else 0) else: stk.append( z3.If(s0 == 0, z3.BitVecVal(1, 256), z3.BitVecVal(0, 256))) elif op == 'AND': stk.append(stk.pop() & stk.pop()) elif op == 'OR': stk.append(stk.pop() | stk.pop()) elif op == 'XOR': stk.append(stk.pop() ^ stk.pop()) elif op == 'NOT': stk.append(~stk.pop()) elif op == 'BYTE': s0, s1 = stk.pop(), stk.pop() if concrete(s0): if s0 >= 32: stk.append(0) else: if concrete(s1): stk.append((s1 // 256**(31 - s0)) % 256) else: v = z3.simplify( z3.Extract((31 - s0) * 8 + 7, (31 - s0) * 8, s1)) if z3.is_bv_value(v): stk.append(v.as_long()) else: stk.append(z3.ZeroExt(256 - 32, v)) else: raise SymbolicError('symbolic byte-index not supported') elif op == 'SHL': s0, s1 = stk.pop(), stk.pop() stk.append((s1 << s0)) elif op == 'SHR': s0, s1 = stk.pop(), stk.pop() if concrete(s1) and concrete(s0): stk.append((s1 >> s0)) else: stk.append(z3.LShR(s1, s0)) elif op == 'SAR': s0, s1 = stk.pop(), teether.util.utils.to_signed(stk.pop()) stk.append((s1 >> s0)) # SHA3 and environment info elif opcode < 0x40: if op == 'SHA3': s0, s1 = stk.pop(), stk.pop() mem.extend(s0, s1) mm = mem.read(s0, s1) if not isinstance(mm, SymRead) and all( concrete(m) for m in mm): data = teether.util.utils.bytearray_to_bytestr(mm) stk.append( teether.util.utils.big_endian_to_int( teether.util.utils.sha3(data))) else: if not isinstance(mm, SymRead): sha_data = z3.simplify( z3.Concat([ m if z3.is_expr(m) else z3.BitVecVal(m, 8) for m in mm ])) for k, v in sha_constraints.items(): if isinstance(v, SymRead): continue if v.size() == sha_data.size() and is_true( v == sha_data): sha = k break else: sha = z3.BitVec( 'SHA3_%x_%d' % (instruction_count, xid), 256) sha_constraints[sha] = sha_data else: sha_data = mm sha = z3.BitVec( 'SHA3_%x_%d' % (instruction_count, xid), 256) sha_constraints[sha] = sha_data stk.append(sha) # raise SymbolicError('symbolic computation of SHA3 not supported') elif op == 'ADDRESS': stk.append(ctx_or_symbolic('ADDRESS', ctx, xid)) elif op == 'BALANCE': s0 = stk.pop() if concrete(s0): stk.append(ctx_or_symbolic('BALANCE-%x' % s0, ctx, xid)) elif is_true( addr(s0) == addr(ctx_or_symbolic('ADDRESS', ctx, xid))): stk.append(state.balance) elif is_true( addr(s0) == addr(ctx_or_symbolic('ORIGIN', ctx, xid))): stk.append(ctx_or_symbolic('BALANCE-ORIGIN', ctx, xid)) elif is_true( addr(s0) == addr(ctx_or_symbolic('CALLER', ctx, xid))): stk.append(ctx_or_symbolic('BALANCE-CALLER', ctx, xid)) else: raise SymbolicError('balance of symbolic address (%s)' % str(z3.simplify(s0))) elif op == 'ORIGIN': stk.append(ctx_or_symbolic('ORIGIN', ctx, xid)) elif op == 'CALLER': stk.append(ctx_or_symbolic('CALLER', ctx, xid)) elif op == 'CALLVALUE': stk.append(ctx_or_symbolic('CALLVALUE', ctx, xid)) elif op == 'CALLDATALOAD': s0 = stk.pop() constraints.append(z3.UGE(calldatasize, s0 + 32)) calldata_accesses.append(s0 + 32) if not concrete(s0): constraints.append(z3.ULT(s0, MAX_CALLDATA_SIZE)) stk.append(z3.Concat([calldata[s0 + i] for i in range(32)])) elif op == 'CALLDATASIZE': stk.append(calldatasize) elif op == 'CALLDATACOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() constraints.append(z3.UGE(calldatasize, dstart + size)) calldata_accesses.append(dstart + size) if not concrete(dstart): constraints.append(z3.ULT(dstart, MAX_CALLDATA_SIZE)) if concrete(size): for i in range(size): mem[mstart + i] = calldata[dstart + i] else: constraints.append(z3.ULT(size, MAX_CALLDATA_SIZE)) for i in range(MAX_CALLDATA_SIZE): mem[mstart + i] = z3.If(size < i, mem[mstart + i], calldata[dstart + i]) elif op == 'CODESIZE': stk.append(len(state.code)) elif op == 'CODECOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if concrete(mstart) and concrete(dstart) and concrete(size): mem.extend(mstart, size) for i in range(size): if dstart + i < len(state.code): mem[mstart + i] = state.code[dstart + i] else: mem[mstart + i] = 0 else: raise SymbolicError('Symbolic code index @ %s' % ins) elif op == 'RETURNDATACOPY': raise ExternalData('RETURNDATACOPY') elif op == 'RETURNDATASIZE': raise ExternalData('RETURNDATASIZE') elif op == 'GASPRICE': stk.append(ctx_or_symbolic('GASPRICE', ctx, xid)) elif op == 'EXTCODESIZE': s0 = stk.pop() if concrete(s0): stk.append(ctx_or_symbolic('CODESIZE-%x' % s0, ctx, xid)) elif is_true(s0 == addr(ctx_or_symbolic('ADDRESS', ctx, xid))): stk.append(ctx_or_symbolic('CODESIZE-ADDRESS', ctx, xid)) elif is_true(s0 == addr(ctx_or_symbolic('CALLER', ctx, xid))): stk.append(ctx_or_symbolic('CODESIZE-CALLER', ctx, xid)) else: raise SymbolicError('codesize of symblic address') elif op == 'EXTCODECOPY': raise ExternalData('EXTCODECOPY') # Block info elif opcode < 0x50: if op == 'BLOCKHASH': s0 = stk.pop() if not concrete(s0): raise SymbolicError('symbolic blockhash index') stk.append(ctx_or_symbolic('BLOCKHASH[%d]' % s0, xid)) elif op == 'COINBASE': stk.append(ctx_or_symbolic('COINBASE', ctx, xid)) elif op == 'TIMESTAMP': ts = ctx_or_symbolic('TIMESTAMP', ctx, xid) if not concrete(ts): constraints.append(z3.UGE(ts, min_timestamp)) constraints.append(z3.ULE(ts, max_timestamp)) stk.append(ts) elif op == 'NUMBER': stk.append(ctx_or_symbolic('NUMBER', ctx, xid)) elif op == 'DIFFICULTY': stk.append(ctx_or_symbolic('DIFFICULTY', ctx, xid)) elif op == 'GASLIMIT': stk.append(ctx_or_symbolic('GASLIMIT', ctx, xid)) # VM state manipulations elif opcode < 0x60: if op == 'POP': stk.pop() elif op == 'MLOAD': s0 = stk.pop() mem.extend(s0, 32) mm = [mem[s0 + i] for i in range(32)] if all(concrete(m) for m in mm): stk.append( teether.util.utils.bytes_to_int(mem.read(s0, 32))) else: v = z3.simplify( z3.Concat([ m if not concrete(m) else z3.BitVecVal(m, 8) for m in mm ])) if z3.is_bv_value(v): stk.append(v.as_long()) else: stk.append(v) elif op == 'MSTORE': s0, s1 = stk.pop(), stk.pop() mem.extend(s0, 32) if concrete(s1): mem.write(s0, 32, teether.util.utils.encode_int32(s1)) else: for i in range(32): m = z3.simplify( z3.Extract((31 - i) * 8 + 7, (31 - i) * 8, s1)) if z3.is_bv_value(m): mem[s0 + i] = m.as_long() else: mem[s0 + i] = m elif op == 'MSTORE8': s0, s1 = stk.pop(), stk.pop() mem.extend(s0, 1) mem[s0] = s1 % 256 elif op == 'SLOAD': s0 = stk.pop() v = z3.simplify(storage[s0]) if z3.is_bv_value(v): stk.append(v.as_long()) else: stk.append(v) elif op == 'SSTORE': s0, s1 = stk.pop(), stk.pop() storage[s0] = s1 elif op == 'JUMP': s0 = stk.pop() if not concrete(s0): raise SymbolicError('Symbolic jump target') state.pc = s0 if state.pc >= len(state.code) or not program[ state.pc].name == 'JUMPDEST': raise VMException('BAD JUMPDEST') continue elif op == 'JUMPI': s0, s1 = stk.pop(), stk.pop() next_target = path[0] if concrete(s1): if s1: if not concrete(s0): raise SymbolicError('Symbolic jump target') if s0 != next_target and state.pc + 1 == next_target: raise IntractablePath(state.trace, path) state.pc = s0 if state.pc >= len(state.code) or not program[ state.pc].name == 'JUMPDEST': raise VMException('BAD JUMPDEST') continue else: if concrete(s0): if state.pc + 1 != next_target and s0 == next_target: raise IntractablePath(state.trace, path) else: if state.pc + 1 == next_target: if not (concrete(s0) and s0 == next_target): constraints.append(s1 == 0) elif concrete(s0) and s0 == next_target: if state.pc + 1 != next_target: constraints.append(s1 != 0) state.pc = s0 if state.pc >= len(state.code) or not program[ state.pc].name == 'JUMPDEST': raise VMException('BAD JUMPDEST') continue elif not concrete(s0): raise SymbolicError('Symbolic jump target') else: raise IntractablePath(state.trace, path) elif op == 'PC': stk.append(state.pc) elif op == 'MSIZE': stk.append(len(mem)) elif op == 'GAS': stk.append(z3.BitVec('GAS_%x' % instruction_count, 256)) # DUPn (eg. DUP1: a b c -> a b c c, DUP3: a b c -> a b c a) elif op[:3] == 'DUP': stk.append( stk[0x7f - opcode] ) # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for 0x8f # SWAPn (eg. SWAP1: a b c d -> a b d c, SWAP3: a b c d -> d b c a) elif op[:4] == 'SWAP': # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for 0x9f stk[-1], stk[0x8e - opcode] = stk[0x8e - opcode], stk[-1] # Logs (aka "events") elif op[:3] == 'LOG': """ 0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas a. Opcodes LOG0...LOG4 are added, takes 2-6 stack arguments MEMSTART MEMSZ (TOPIC1) (TOPIC2) (TOPIC3) (TOPIC4) b. Logs are kept track of during tx execution exactly the same way as selfdestructs (except as an ordered list, not a set). Each log is in the form [address, [topic1, ... ], data] where: * address is what the ADDRESS opcode would output * data is mem[MEMSTART: MEMSTART + MEMSZ] * topics are as provided by the opcode c. The ordered list of logs in the transaction are expressed as [log0, log1, ..., logN]. """ depth = int(op[3:]) mstart, msz = stk.pop(), stk.pop() topics = [stk.pop() for _ in range(depth)] mem.extend(mstart, msz) # Ignore external effects... # Create a new contract elif op == 'CREATE': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() constraints.append(z3.UGE(state.balance, s0)) state.balance -= s0 stk.append( addr( z3.BitVec('EXT_CREATE_%d_%d' % (instruction_count, xid), 256))) # Calls elif op in ('CALL', 'CALLCODE', 'DELEGATECALL', 'STATICCALL'): if op in ('CALL', 'CALLCODE'): s0, s1, s2, s3, s4, s5, s6 = stk.pop(), stk.pop(), stk.pop( ), stk.pop(), stk.pop(), stk.pop(), stk.pop() if op == 'CALL': constraints.append(z3.UGE(state.balance, s2)) state.balance -= s2 elif op == 'DELEGATECALL': s0, s1, s3, s4, s5, s6 = stk.pop(), stk.pop(), stk.pop( ), stk.pop(), stk.pop(), stk.pop() s2 = ctx_or_symbolic('CALLVALUE', ctx, xid) elif op == 'STATICCALL': s0, s1, s3, s4, s5, s6 = stk.pop(), stk.pop(), stk.pop( ), stk.pop(), stk.pop(), stk.pop() s2 = 0 ostart = s5 if concrete(s5) else z3.simplify(s5) olen = s6 if concrete(s6) else z3.simplify(s6) if concrete(s1) and s1 <= 8: if s1 == 4: logging.info("Calling precompiled identity contract") istart = s3 if concrete(s3) else z3.simplify(s3) ilen = s4 if concrete(s4) else z3.simplify(s4) mem.copy(istart, ilen, ostart, olen) stk.append(1) else: raise SymbolicError( "Precompiled contract %d not implemented" % s1) else: for i in range(olen): mem[ostart + i] = z3.BitVec( 'EXT_%d_%d_%d' % (instruction_count, i, xid), 8) logging.info("Calling contract %s (%d_%d)" % (s1, instruction_count, xid)) stk.append( z3.BitVec('CALLRESULT_%d_%d' % (instruction_count, xid), 256)) elif op == 'RETURN': s0, s1 = stk.pop(), stk.pop() if concrete(s0) and concrete(s1): mem.extend(s0, s1) state.success = True if path: raise IntractablePath(state.trace, path) constraints.append( z3.Or(*(z3.ULE(calldatasize, access) for access in calldata_accesses))) return SymbolicResult(xid, state, constraints, sha_constraints, target_op) # Revert opcode (Metropolis) elif op == 'REVERT': s0, s1 = stk.pop(), stk.pop() if not concrete(s0) or not concrete(s1): raise SymbolicError('symbolic memory index') mem.extend(s0, s1) if path: raise IntractablePath(state.trace, path) constraints.append( z3.Or(*(z3.ULE(calldatasize, access) for access in calldata_accesses))) return SymbolicResult(xid, state, constraints, sha_constraints, target_op) # SELFDESTRUCT opcode (also called SELFDESTRUCT) elif op == 'SELFDESTRUCT': s0 = stk.pop() state.success = True if path: raise IntractablePath(state.trace, path) constraints.append( z3.Or(*(z3.ULE(calldatasize, access) for access in calldata_accesses))) return SymbolicResult(xid, state, constraints, sha_constraints, target_op) state.pc += 1 if path: raise IntractablePath(state.trace, path) state.success = True return SymbolicResult(xid, state, constraints, sha_constraints, target_op)
def generate_assignments(thresh=2): solver = z3.Solver() # Block 1 block_1 = {'b1_1': 'move'} block_1_obj = SMT_Block(block_1, thresh) values = block_1_obj.block_values block_1_vars = [ele.var for ele in block_1_obj.block_z3_vars ] # for the conditional constraints c1 = z3.Int('c1') # bool_path_left (if_only) values.append(z3.Or(c1 == 8, c1 == 9)) block_2 = {'b2_1': 'turn_left'} block_2_obj = SMT_Block(block_2, thresh) values.extend(block_2_obj.block_values) block_2_vars = [ele.var for ele in block_2_obj.block_z3_vars ] # for the conditional constraints block_3 = {'b3_1': 'phi'} block_3_obj = SMT_Block(block_3, thresh) values.extend(block_3_obj.block_values) block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars ] # for the conditional constraints # all block objects block_objs = [block_1_obj, block_2_obj, block_3_obj] X = [ele.var for ele in block_1_obj.block_z3_vars ] # added the variables for block 1 X.append(c1) # added the conditional variable X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 X.extend([ele.var for ele in block_3_obj.block_z3_vars ]) # added the variables for block 3 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + block_2_obj.block_elimination_constraints + \ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + block_3_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) constraints.extend([ # conditional constraints: if(path_left) z3.Implies(c1 == 8, z3.Or(block_2_vars[0] == 2, block_2_vars[1] == 2, block_2_vars[2] == 2, block_2_vars[3] == 2, block_2_vars[4] == 2, )), z3.Implies(z3.And(c1 == 8, block_2_vars[1] == 2, block_2_vars[0] != 2), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 3 )), z3.Implies(z3.And(c1 == 8, block_2_vars[2] == 2, block_2_vars[0] != 2, block_2_vars[1] != 2), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 3, block_2_vars[1] != 1, block_2_vars[1] != 3)), z3.Implies(z3.And(c1 == 8, block_2_vars[3] == 2, block_2_vars[0] != 2, block_2_vars[1] != 2, block_2_vars[2] != 2), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 3, block_2_vars[1] != 1, \ block_2_vars[1] != 3, block_2_vars[2] != 1, block_2_vars[2] != 3)), z3.Implies(z3.And(c1 == 8, block_2_vars[4] == 2, block_2_vars[0] != 2, block_2_vars[1] != 2, block_2_vars[2] != 2, block_2_vars[3] != 2), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 3, block_2_vars[1] != 1, block_2_vars[1] != 3, block_2_vars[2] != 1, block_2_vars[2] != 3, block_2_vars[3] != 1, block_2_vars[3] != 3)), # conditional constraints: if(path_right) z3.Implies(c1 == 9, z3.Or(block_2_vars[0] == 3, block_2_vars[1] == 3, block_2_vars[2] == 3, block_2_vars[3] == 3, block_2_vars[4] == 3, )), z3.Implies(z3.And(c1 == 9, block_2_vars[1] == 3, block_2_vars[0] != 3, ), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 2)), z3.Implies(z3.And(c1 == 9, block_2_vars[2] == 3, block_2_vars[0] != 3, block_2_vars[1] != 3), z3.And(block_2_vars[0]!= 1, block_2_vars[0] != 2, block_2_vars[1] != 1, block_2_vars[1] != 2)), z3.Implies(z3.And(c1 == 9, block_2_vars[3] == 3, block_2_vars[0] != 3, block_2_vars[1] != 3, block_2_vars[2] != 3), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 2, block_2_vars[1] != 1, block_2_vars[1] != 2, block_2_vars[2] != 1, block_2_vars[2] != 2)), z3.Implies(z3.And(c1 == 9, block_2_vars[4] == 3, block_2_vars[0] != 3, block_2_vars[1] != 3, block_2_vars[2] != 3, block_2_vars[3] != 3 ), z3.And(block_2_vars[0] != 1, block_2_vars[0] != 2, block_2_vars[1] != 1, block_2_vars[1] != 2, block_2_vars[2] != 1, block_2_vars[2] != 2, block_2_vars[3] != 1, block_2_vars[3] != 2)), ]) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = ['repeat_until_goal(bool_goal)'] a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in X[:block_1_obj.size] ]) a.append(type_to_str[ConditionalType(model[c1].as_long())]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in X[block_1_obj.size + 1:] ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def generate_assignments(thresh=2, id='karel'): solver = z3.Solver() # declare the SMT variables for the specific code # Block 1 block_1 = {'b1_1': 'put_marker'} block_1_obj = SMT_Block(block_1, thresh, id=id) values = block_1_obj.block_values block_1_vars = [ele.var for ele in block_1_obj.block_z3_vars ] # for the conditional constraints c1 = z3.Int('c1') # bool_path_ahead (while) values.append(z3.Or(c1 == 7, c1 == 12)) # bool_path_ahead, bool_no_path_ahead block_2 = { 'b2_1': 'move', 'b2_2': 'turn_left', 'b2_3': 'move', 'b2_4': 'turn_right', 'b2_5': 'put_marker' } block_2_obj = SMT_Block(block_2, thresh, id=id) values.extend(block_2_obj.block_values) block_2_vars = [ele.var for ele in block_2_obj.block_z3_vars ] # for the conditional constraints block_3 = {'b3_1': 'phi'} block_3_obj = SMT_Block(block_3, thresh, id=id) values.extend(block_3_obj.block_values) block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars ] # for the conditional constraints # all block objects block_objs = [block_1_obj, block_2_obj, block_3_obj] X = [c1] X.extend([ele.var for ele in block_1_obj.block_z3_vars ]) # added the variables for block 1 X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 X.extend([ele.var for ele in block_3_obj.block_z3_vars ]) # added the variables for block 3 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.flip_marker_constraints+ \ block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + \ block_2_obj.flip_marker_constraints + block_2_obj.block_elimination_constraints +\ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + \ block_3_obj.flip_marker_constraints + block_3_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) constraints.extend([ # conditional constraints: while(bool_path_ahead)---while block constraints z3.Implies( c1 == 7, z3.Or( block_2_vars[0] == 1, block_2_vars[1] == 1, block_2_vars[2] == 1, block_2_vars[3] == 1, block_2_vars[4] == 1, block_2_vars[5] == 1, block_2_vars[6] == 1, block_2_vars[7] == 1, block_2_vars[8] == 1, block_2_vars[9] == 1, block_2_vars[10] == 1, block_2_vars[11] == 1, block_2_vars[12] == 1, )), z3.Implies(z3.And(c1 == 7, block_2_vars[1] == 1, block_2_vars[0] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[2] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[3] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[4] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[5] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[6] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[7] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[8] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3, block_2_vars[7] != 2, block_2_vars[7] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[9] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3, block_2_vars[7] != 2, block_2_vars[7] != 3, block_2_vars[8] != 2, block_2_vars[8] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[10] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3, block_2_vars[7] != 2, block_2_vars[7] != 3, block_2_vars[8] != 2, block_2_vars[8] != 3, block_2_vars[9] != 2, block_2_vars[9] != 3)), # # ################################################ THRESH = 2 z3.Implies( z3.And(c1 == 7, block_2_vars[11] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1, block_2_vars[10] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3, block_2_vars[7] != 2, block_2_vars[7] != 3, block_2_vars[8] != 2, block_2_vars[8] != 3, block_2_vars[9] != 2, block_2_vars[9] != 3, block_2_vars[10] != 2, block_2_vars[10] != 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[12] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1, block_2_vars[10] != 1, block_2_vars[11] != 1), z3.And(block_2_vars[0] != 2, block_2_vars[0] != 3, block_2_vars[1] != 2, block_2_vars[1] != 3, block_2_vars[2] != 2, block_2_vars[2] != 3, block_2_vars[3] != 2, block_2_vars[3] != 3, block_2_vars[4] != 2, block_2_vars[4] != 3, block_2_vars[5] != 2, block_2_vars[5] != 3, block_2_vars[6] != 2, block_2_vars[6] != 3, block_2_vars[7] != 2, block_2_vars[7] != 3, block_2_vars[8] != 2, block_2_vars[8] != 3, block_2_vars[9] != 2, block_2_vars[9] != 3, block_2_vars[10] != 2, block_2_vars[10] != 3, block_2_vars[11] != 2, block_2_vars[11] != 3)), # # conditional constraints: while(bool_no_path_ahead)---while block constraints z3.Implies(c1 == 12, block_2_vars[0] != 1), z3.Implies( z3.And(c1 == 12, block_2_vars[1] == 1, block_2_vars[0] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[2] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[3] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[4] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[5] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[6] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[7] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[8] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3, block_2_vars[7] == 2, block_2_vars[7] == 3)), z3.Implies( z3.And(c1 == 12, block_2_vars[9] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3, block_2_vars[7] == 2, block_2_vars[7] == 3, block_2_vars[8] == 2, block_2_vars[8] == 3)), z3.Implies( z3.And( c1 == 12, block_2_vars[10] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1, ), z3.Or( block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3, block_2_vars[7] == 2, block_2_vars[7] == 3, block_2_vars[8] == 2, block_2_vars[8] == 3, block_2_vars[9] == 2, block_2_vars[9] == 3, )), z3.Implies( z3.And(c1 == 12, block_2_vars[11] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1, block_2_vars[10] != 1), z3.Or( block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3, block_2_vars[7] == 2, block_2_vars[7] == 3, block_2_vars[8] == 2, block_2_vars[8] == 3, block_2_vars[9] == 2, block_2_vars[9] == 3, block_2_vars[10] == 2, block_2_vars[10] == 3, )), z3.Implies( z3.And(c1 == 12, block_2_vars[12] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1, block_2_vars[4] != 1, block_2_vars[5] != 1, block_2_vars[6] != 1, block_2_vars[7] != 1, block_2_vars[8] != 1, block_2_vars[9] != 1, block_2_vars[10] != 1, block_2_vars[11] != 1), z3.Or( block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3, block_2_vars[4] == 2, block_2_vars[4] == 3, block_2_vars[5] == 2, block_2_vars[5] == 3, block_2_vars[6] == 2, block_2_vars[6] == 3, block_2_vars[7] == 2, block_2_vars[7] == 3, block_2_vars[8] == 2, block_2_vars[8] == 3, block_2_vars[9] == 2, block_2_vars[9] == 3, block_2_vars[10] == 2, block_2_vars[10] == 3, block_2_vars[11] == 2, block_2_vars[11] == 3, )), ]) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [ type_to_str[VariableType(model[ele].as_long())] for ele in block_1_vars ] a.append(type_to_str[ConditionalType(model[c1].as_long())]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_2_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def generate_assignments(thresh = 2, id = 'karel'): # create the initial z3 solver solver = z3.Solver() # declare a block block_1 = {'b1_1': 'put_marker', 'b1_2': 'move', 'b1_3': 'turn_left'} block_1_obj = SMT_Block(block_1, thresh, id =id ) values = block_1_obj.block_values c1 = z3.Int('c1') # 4 (repeat) values.append( z3.Or(c1 == 3, c1 == 4, c1 == 5), ) # declare a block block_2 = {'b2_1': 'phi'} block_2_obj = SMT_Block(block_2, thresh, id=id) values.extend(block_2_obj.block_values) # declare a block block_3 = {'b3_1': 'phi'} block_3_obj = SMT_Block(block_3, thresh, id=id) values.extend(block_3_obj.block_values) block_objs = [block_1_obj, block_2_obj, block_3_obj] # declare the values that each of the variables can take X = [ele.var for ele in block_1_obj.block_z3_vars] X.append(c1) X.extend([ele.var for ele in block_2_obj.block_z3_vars]) X.extend([ele.var for ele in block_3_obj.block_z3_vars]) constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + \ block_1_obj.flip_marker_constraints + block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + \ block_2_obj.flip_marker_constraints + block_2_obj.block_elimination_constraints + \ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + \ block_3_obj.flip_marker_constraints + block_3_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [str(model[c1].as_long())] a.extend([type_to_str[VariableType(model[ele.var].as_long())] for ele in block_1_obj.block_z3_vars ]) a.extend([type_to_str[VariableType(model[ele.var].as_long())] for ele in block_2_obj.block_z3_vars ]) a.extend([type_to_str[VariableType(model[ele.var].as_long())] for ele in block_3_obj.block_z3_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def generate_assignments(thresh=2): solver = z3.Solver() # declare the SMT variables for the specific code block_1 = {'b1_1': 'move'} block_1_obj = SMT_Block(block_1, thresh) values = block_1_obj.block_values block_1_vars = [ele.var for ele in block_1_obj.block_z3_vars ] # for the conditional constraints c1 = z3.Int('c1') # 4 (repeat) values.append(z3.Or(c1 == 3, c1 == 4, c1 == 5), ) block_2 = {'b2_1': 'turn_left'} block_2_obj = SMT_Block(block_2, thresh) values.extend(block_2_obj.block_values) block_2_vars = [ele.var for ele in block_2_obj.block_z3_vars ] # for the conditional constraints c2 = z3.Int('c2') # 5 (repeat) values.append(z3.Or(c2 == 4, c2 == 5, c2 == 6), ) block_3 = {'b3_1': 'move'} block_3_obj = SMT_Block(block_3, thresh) values.extend(block_3_obj.block_values) block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars ] # for the conditional constraints # add another block in the beginning of the code block_4 = {'b4_1': 'phi'} block_4_obj = SMT_Block(block_4, thresh) values.extend(block_4_obj.block_values) block_4_vars = [ele.var for ele in block_4_obj.block_z3_vars] # add another block in the end of the code block_5 = {'b5_1': 'phi'} block_5_obj = SMT_Block(block_5, thresh) values.extend(block_5_obj.block_values) block_5_vars = [ele.var for ele in block_5_obj.block_z3_vars] # all block objects block_objs = [ block_1_obj, block_2_obj, block_3_obj, block_4_obj, block_5_obj ] X = [ele.var for ele in block_1_obj.block_z3_vars ] # added the variables for block 1 X.append(c1) # added the conditional variable X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 X.append(c2) # added the conditional variable X.extend([ele.var for ele in block_3_obj.block_z3_vars ]) # added the variables for block 3 X.extend([ele.var for ele in block_4_obj.block_z3_vars ]) # added the variables for block 4 X.extend([ele.var for ele in block_5_obj.block_z3_vars ]) # added the variables for block 5 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + block_2_obj.block_elimination_constraints + \ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + block_3_obj.block_elimination_constraints + \ block_4_obj.block_append_constraints + block_4_obj.flip_turns_constraints + block_4_obj.block_elimination_constraints + \ block_5_obj.block_append_constraints + block_5_obj.flip_turns_constraints + block_5_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [str(model[c1].as_long())] a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_1_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_2_vars ]) a.append(str(model[c2].as_long())) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_4_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_5_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def generate_assignments(thresh=2, id='karel'): solver = z3.Solver() # declare the SMT variables for the specific code # Block 1 c0 = z3.Int('c0') # repeat (8) c1 = z3.Int('c1') # bool_no_marker (if_else) block_1 = {'b1_1': 'put_marker'} block_1_obj = SMT_Block(block_1, thresh, id=id) values = block_1_obj.block_values block_1_vars = [ele.var for ele in block_1_obj.block_z3_vars ] # for the conditional constraints block_2 = {'b2_1': 'pick_marker'} block_2_obj = SMT_Block(block_2, thresh, id=id) values.extend(block_2_obj.block_values) block_2_vars = [ele.var for ele in block_2_obj.block_z3_vars ] # for the conditional constraints values.append(z3.Or(c0 == 7, c0 == 8, c0 == 9)) values.append(z3.Or(c1 == 10, c1 == 11)) # bool_no_marker, bool_marker block_3 = {'b3_1': 'move'} block_3_obj = SMT_Block(block_3, thresh, id=id) values.extend(block_3_obj.block_values) block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars ] # for the conditional constraints block_4 = {'b4_1': 'phi'} block_4_obj = SMT_Block(block_4, thresh, id=id) values.extend(block_4_obj.block_values) block_4_vars = [ele.var for ele in block_4_obj.block_z3_vars ] # for the conditional constraints block_5 = {'b5_1': 'phi'} block_5_obj = SMT_Block(block_5, thresh, id=id) values.extend(block_5_obj.block_values) block_5_vars = [ele.var for ele in block_5_obj.block_z3_vars ] # for the conditional constraints # all block objects block_objs = [ block_1_obj, block_2_obj, block_3_obj, block_4_obj, block_5_obj ] X = [c0, c1] X.extend([ele.var for ele in block_1_obj.block_z3_vars ]) # added the variables for block 1 X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 X.extend([ele.var for ele in block_3_obj.block_z3_vars ]) # added the variables for block 3 X.extend([ele.var for ele in block_4_obj.block_z3_vars ]) # added the variables for block 4 X.extend([ele.var for ele in block_5_obj.block_z3_vars ]) # added the variables for block 5 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.flip_marker_constraints+ \ block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + \ block_2_obj.flip_marker_constraints+block_2_obj.block_elimination_constraints + \ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + \ block_3_obj.flip_marker_constraints+block_3_obj.block_elimination_constraints + \ block_4_obj.block_append_constraints + block_4_obj.flip_turns_constraints + \ block_4_obj.flip_marker_constraints + block_4_obj.block_elimination_constraints + \ block_5_obj.block_append_constraints + block_5_obj.flip_turns_constraints + \ block_5_obj.flip_marker_constraints + block_5_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) constraints.extend([ # conditional constraints: if_else(bool_no_marker)---if block constraints z3.Implies(c1 == 11, block_1_vars[0] != 4), z3.Implies( z3.And(c1 == 11, block_1_vars[1] == 4, block_1_vars[0] != 4), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 5)), z3.Implies( z3.And(c1 == 11, block_1_vars[2] == 4, block_1_vars[0] != 4, block_1_vars[1] != 4), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 5, block_1_vars[1] == 1, block_1_vars[1] == 5)), z3.Implies( z3.And(c1 == 11, block_1_vars[3] == 4, block_1_vars[0] != 4, block_1_vars[1] != 4, block_1_vars[2] != 4), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 5, block_1_vars[1] == 1, block_1_vars[1] == 5, block_1_vars[2] == 1, block_1_vars[2] == 5)), z3.Implies( z3.And(c1 == 11, block_1_vars[4] == 4, block_1_vars[0] != 4, block_1_vars[1] != 4, block_1_vars[2] != 4, block_1_vars[3] != 4), z3.And(block_1_vars[0] == 1, block_1_vars[0] == 5, block_1_vars[1] == 1, block_1_vars[1] == 5, block_1_vars[2] == 1, block_1_vars[2] == 5, block_1_vars[3] == 1, block_1_vars[3] == 5)), # else block constraints z3.Implies(c1 == 11, block_2_vars[0] != 5), z3.Implies( z3.And(c1 == 11, block_2_vars[1] == 5, block_2_vars[0] != 5), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 4)), z3.Implies( z3.And(c1 == 11, block_2_vars[2] == 5, block_2_vars[0] != 5, block_2_vars[1] != 5), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 4, block_2_vars[1] == 1, block_2_vars[1] == 4)), z3.Implies( z3.And(c1 == 11, block_2_vars[3] == 5, block_2_vars[0] != 5, block_2_vars[1] != 5, block_2_vars[2] != 5), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 4, block_2_vars[1] == 1, block_2_vars[1] == 4, block_2_vars[2] == 1, block_2_vars[2] == 4)), z3.Implies( z3.And(c1 == 11, block_2_vars[4] == 5, block_2_vars[0] != 5, block_2_vars[1] != 5, block_2_vars[2] != 5, block_2_vars[3] != 5), z3.And(block_2_vars[0] == 1, block_2_vars[0] == 4, block_2_vars[1] == 1, block_2_vars[1] == 4, block_2_vars[2] == 1, block_2_vars[2] == 4, block_2_vars[3] == 1, block_2_vars[3] == 4)), # conditional constraints: if_else(bool_marker)---if block constraints z3.Implies(c1 == 10, block_1_vars[0] != 5), z3.Implies( z3.And(c1 == 10, block_1_vars[1] == 5, block_1_vars[0] != 5), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 4)), z3.Implies( z3.And(c1 == 10, block_1_vars[2] == 5, block_1_vars[0] != 5, block_1_vars[1] != 5), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 4, block_1_vars[1] == 1, block_1_vars[1] == 4)), z3.Implies( z3.And(c1 == 10, block_1_vars[3] == 5, block_1_vars[0] != 5, block_1_vars[1] != 5, block_1_vars[2] != 5), z3.Or(block_1_vars[0] == 1, block_1_vars[0] == 4, block_1_vars[1] == 1, block_1_vars[1] == 4, block_1_vars[2] == 1, block_1_vars[2] == 4)), z3.Implies( z3.And(c1 == 10, block_1_vars[4] == 5, block_1_vars[0] != 5, block_1_vars[1] != 5, block_1_vars[2] != 5, block_1_vars[3] != 5), z3.And(block_1_vars[0] == 1, block_1_vars[0] == 4, block_1_vars[1] == 1, block_1_vars[1] == 4, block_1_vars[2] == 1, block_1_vars[2] == 4, block_1_vars[3] == 1, block_1_vars[3] == 4)), # else block constraints z3.Implies(c1 == 10, block_2_vars[0] != 4), z3.Implies( z3.And(c1 == 10, block_2_vars[1] == 4, block_2_vars[0] != 4), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 5)), z3.Implies( z3.And(c1 == 10, block_2_vars[2] == 4, block_2_vars[0] != 4, block_2_vars[1] != 4), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 5, block_2_vars[1] == 1, block_2_vars[1] == 5)), z3.Implies( z3.And(c1 == 10, block_2_vars[3] == 4, block_2_vars[0] != 4, block_2_vars[1] != 4, block_2_vars[2] != 4), z3.Or(block_2_vars[0] == 1, block_2_vars[0] == 5, block_2_vars[1] == 1, block_2_vars[1] == 5, block_2_vars[2] == 1, block_2_vars[2] == 5)), z3.Implies( z3.And(c1 == 10, block_2_vars[4] == 4, block_2_vars[0] != 4, block_2_vars[1] != 4, block_2_vars[2] != 4, block_2_vars[3] != 4), z3.And(block_2_vars[0] == 1, block_2_vars[0] == 5, block_2_vars[1] == 1, block_2_vars[1] == 5, block_2_vars[2] == 1, block_2_vars[2] == 5, block_2_vars[3] == 1, block_2_vars[3] == 5)), ]) unequal_blocks_con = block_unequal_constraint(block_1_obj, block_2_obj) constraints.extend(unequal_blocks_con) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [ str(model[c0].as_long()), type_to_str[ConditionalType(model[c1].as_long())] ] a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_1_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_2_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_4_vars ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_5_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def generate_assignments(thresh=2): solver = z3.Solver() # declare the SMT variables for the specific code # Block 1 block_1 = {'b1_1': 'move'} block_1_obj = SMT_Block(block_1, thresh) values = block_1_obj.block_values block_1_vars = [ele.var for ele in block_1_obj.block_z3_vars ] # for the conditional constraints c1 = z3.Int('c1') # bool_path_ahead (if_else) block_2 = {'b2_1': 'turn_left'} block_2_obj = SMT_Block(block_2, thresh) values.extend(block_2_obj.block_values) block_2_vars = [ele.var for ele in block_2_obj.block_z3_vars ] # for the conditional constraints values.append(c1 == 7) # same conditional value block_3 = {'b3_1': 'phi'} block_3_obj = SMT_Block(block_3, thresh) values.extend(block_3_obj.block_values) block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars ] # for the conditional constraints # all block objects block_objs = [block_1_obj, block_2_obj, block_3_obj] X = [c1] X.extend([ele.var for ele in block_1_obj.block_z3_vars ]) # added the variables for block 1 X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 X.extend([ele.var for ele in block_3_obj.block_z3_vars ]) # added the variables for block 2 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.block_elimination_constraints + \ block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + block_2_obj.block_elimination_constraints + \ block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + block_3_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) constraints.extend([ # conditional constraints: if_else(bool_path_ahead)---if block constraints z3.Implies( c1 == 7, z3.Or( block_1_vars[0] == 1, block_1_vars[1] == 1, block_1_vars[2] == 1, block_1_vars[3] == 1, block_1_vars[4] == 1, )), z3.Implies(z3.And(c1 == 7, block_1_vars[1] == 1, block_1_vars[0] != 1), z3.And(block_1_vars[0] != 2, block_1_vars[0] != 3)), z3.Implies( z3.And(c1 == 7, block_1_vars[2] == 1, block_1_vars[0] != 1, block_1_vars[1] != 1), z3.And(block_1_vars[0] != 2, block_1_vars[0] != 3, block_1_vars[1] != 2, block_1_vars[1] != 3)), z3.Implies( z3.And(c1 == 7, block_1_vars[3] == 1, block_1_vars[0] != 1, block_1_vars[1] != 1, block_1_vars[2] != 1), z3.And(block_1_vars[0] != 2, block_1_vars[0] != 3, block_1_vars[1] != 2, block_1_vars[1] != 3, block_1_vars[2] != 2, block_1_vars[2] != 3)), z3.Implies( z3.And(c1 == 7, block_1_vars[4] == 1, block_1_vars[0] != 1, block_1_vars[1] != 1, block_1_vars[2] != 1, block_1_vars[3] != 1), z3.And(block_1_vars[0] != 2, block_1_vars[0] != 3, block_1_vars[1] != 2, block_1_vars[1] != 3, block_1_vars[2] != 2, block_1_vars[2] != 3, block_1_vars[3] != 2, block_1_vars[3] != 3)), # else block constraints z3.Implies(c1 == 7, block_2_vars[0] != 1), z3.Implies(z3.And(c1 == 7, block_2_vars[1] == 1, block_2_vars[0] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[2] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[3] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3)), z3.Implies( z3.And(c1 == 7, block_2_vars[4] == 1, block_2_vars[0] != 1, block_2_vars[1] != 1, block_2_vars[2] != 1, block_2_vars[3] != 1), z3.Or(block_2_vars[0] == 2, block_2_vars[0] == 3, block_2_vars[1] == 2, block_2_vars[1] == 3, block_2_vars[2] == 2, block_2_vars[2] == 3, block_2_vars[3] == 2, block_2_vars[3] == 3)), ]) unequal_blocks_con = block_unequal_constraint(block_1_obj, block_2_obj) constraints.extend(unequal_blocks_con) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [ 'repeat_until_goal(bool_goal)', type_to_str[ConditionalType(model[c1].as_long())] ] a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in X[1:block_1_obj.size + 1] ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in X[block_1_obj.size + 1:block_2_obj.size + block_1_obj.size + 1] ]) a.extend([ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ]) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
class Z3Context(Context): def __init__(self, *args, **kw): Context.__init__(self, *args, **kw) self.solver = z3.Solver() def __getitem__(self, key): if not isinstance(key, Sort) and key in self.storage: return self.storage[key] elif isinstance(key, Sort): if key.name in self.storage: return self.storage[key.name] val = self.new_from_sort(key) self.storage[key.name] = val return val else: raise ValueError("%s not found! %s. %s." %(key, type(key), self.storage)) def new_from_sort(self, key): if isinstance(key, Bool): key = key.name val = z3.Bool(key) return val elif isinstance(key, Int): key = key.name val = z3.Int(key) return val elif isinstance(key, String): key = key.name val = z3.String(key) return val elif isinstance(key, BitVec): name = key.name size = key.size val = z3.BitVec(name, size) return val raise TypeError("%s not supported!" %type(key)) def s_assert(self, expr): self.solver.assert_exprs(expr.cval(self)) def s_check(self): res = self.solver.check() return res def s_model(self): try: m = self.solver.model() return self.process_model(m) except z3.Z3Exception: return {} def s_push(self): self.solver.push() def s_pop(self): self.solver.pop() def s_reset(self): self.solver.reset() def solve(self, AST): outputs = [] self.s_reset() for node in AST: if isinstance(node, Sort): self.s_assert(node) elif isinstance(node, Let): self.s_assert(node.term) elif isinstance(node, Command): if node.cname == "push": self.s_push() elif node.cname == "pop": self.s_pop() elif node.cname == "check-sat": logger.info("\n-------") outputs.append(self.s_check()) logger.info("Check: %s" % outputs[-1]) elif node.cname == "get-model": outputs.append(self.s_model()) logger.info("Model: %s" % outputs[-1]) else: raise ValueError("Command %s not supported!" %node) return outputs def process_model(self, z3_model): m = {} for v in z3_model: m[v.name()] = self.get_py_value(z3_model.get_interp(v)) return m def get_py_value(self, assignment): if z3.is_ast(assignment): if z3.is_int_value(assignment): return assignment.as_long() if z3.is_bool(assignment): return z3.is_true(assignment) if z3.is_string_value(assignment): try: val = assignment.as_string()[1:-1] # remove quotes val = val.replace("\\x00", "") return str(val) # Z3 throws encoding errors. It can't decode its own solution.. # TODO find a better fix. except UnicodeDecodeError: val = assignment.as_ast() return repr(val) raise ValueError("Unsupported Z3 type! %s" % type(assignment)) return assignment BoolVal = lambda self, x : z3.BoolVal(x) StringVal = lambda self, x : z3.StringVal(x) IntVal = lambda self, x : z3.IntVal(x) BitVecVal = lambda self, val, size : z3.BitVecVal(val, size) And = lambda self, *x : z3.And(x) Or = lambda self, *x : z3.Or(x) Xor = lambda self, *x : reduce(xor, x) Implies = lambda self, x, y : z3.Implies(x, y) Distinct = lambda self, x, y : z3.Distinct(x, y) def Eq(self, x, y): # x = z3.String("x") # x == "test" #throws an error. This is a workaround for now. x = z3.StringVal(x) if isinstance(x,str) else x y = z3.StringVal(y) if isinstance(y,str) else y return eq(x,y) Not = lambda self, x : z3.Not(x) If = lambda self, *x : z3.If(*x) add = lambda self, *x : reduce(add, x) sub = lambda self, *x : reduce(sub, x) if len(x) > 1 else -x[0] mul = lambda self, *x : reduce(mul, x) lt = lambda self, *x : reduce(lt, x) le = lambda self, *x : reduce(le, x) gt = lambda self, *x : reduce(gt, x) ge = lambda self, *x : reduce(ge, x) concat = lambda self, *x : reduce(add, x) length = lambda self, x : z3.Length(x) contains = lambda self, x, y : z3.Contains(x, y) indexof = lambda self, x, y, z=0 : z3.IndexOf(x, y, z) extract = lambda self, x, y, z : z3.Extract(x, y, z) bvadd = add bvsub = sub bvmul = mul bvxor = Xor bvneg = lambda self, x : neg(x) bvnot = lambda self, x : inv(x) bvconcat = lambda self, *x : z3.Concat(*x) bvlshr = lambda self, x, y : z3.LShR(x, y) bvlshl = lambda self, x, y : z3.LShL(x, y) bvuge = lambda self, x, y : z3.UGE(x, y) bvurem = lambda self, x, y : z3.URem(x, y) # TODO Need to define all these with stuff in computation folder FPAbs = lambda self, *x : None FPNeg = lambda self, *x : None FPAdd = lambda self, *x : None FPSub = lambda self, *x : None FPMul = lambda self, *x : None FPDiv = lambda self, *x : None FPFMA = lambda self, *x : None FPRem = lambda self, *x : None FPSqrt = lambda self, *x : None FPRoundToIntegral = lambda self, *x : None FPMin = lambda self, *x : None FPMax = lambda self, *x : None FPLEQ = lambda self, *x : None FPLT = lambda self, *x : None FPGEQ = lambda self, *x : None FPGT = lambda self, *x : None FPEQ = lambda self, *x : None FPIsNormal = lambda self, *x : None FPIsSubNormal = lambda self, *x : None FPIsZero = lambda self, *x : None FPIsInfinite = lambda self, *x : None FPIsNan = lambda self, *x : None FPIsNegative = lambda self, *x : None FPIsPositive = lambda self, *x : None
def generate_assignments(thresh=2): solver = z3.Solver() # declare the SMT variables for the specific code block_1 = {'b1_1': 'turn_right'} block_1_obj = SMT_Block(block_1, thresh) values = block_1_obj.block_values c1 = z3.Int('c1') # 5 (repeat) values.append(z3.Or(c1 == 4, c1 == 5, c1 == 6), ) block_2 = {'b2_1': 'move'} block_2_obj = SMT_Block(block_2, thresh) values.extend(block_2_obj.block_values) # additional empty block added in the end of the code block_3 = {'b3_1': 'phi'} block_3_obj = SMT_Block(block_3, thresh) values.extend(block_3_obj.block_values) # all block objects block_objs = [block_1_obj, block_2_obj, block_3_obj] X = [ele.var for ele in block_1_obj.block_z3_vars ] # added the variables for block 1 X.append(c1) # added the conditional variable X.extend([ele.var for ele in block_2_obj.block_z3_vars ]) # added the variables for block 2 block_3_vars = [ele.var for ele in block_3_obj.block_z3_vars] X.extend(block_3_vars) # added the variables for block 3 constraints = block_1_obj.block_append_constraints + block_1_obj.flip_turns_constraints + block_1_obj.block_elimination_constraints \ + block_2_obj.block_append_constraints + block_2_obj.flip_turns_constraints + block_2_obj.block_elimination_constraints \ + block_3_obj.block_append_constraints + block_3_obj.flip_turns_constraints + block_3_obj.block_elimination_constraints single_block_change_cons = single_block_change(block_objs) constraints.extend(single_block_change_cons) # add the values and the constraints solver.add(values + constraints) # generate all the assignments models = gen_all(solver, X) assignments = [] for model in models: a = [ type_to_str[VariableType(model[ele].as_long())] for ele in X[:block_1_obj.size] ] a.append(str(model[c1].as_long())) b = [ type_to_str[VariableType(model[ele].as_long())] for ele in X[block_2_obj.size + 1:] ] a.extend(b) c = [ type_to_str[VariableType(model[ele].as_long())] for ele in block_3_vars ] a.extend(c) assignments.append(a) #print(a) #print('Found #{} SAT values'.format(len(models))) return assignments
def addOriginSMTConstraints(self): """ Realize to transfer the CCSL constraints into SMT formula. :return: """ cnt = 0 for each in self.newCCSLConstraintList: if each[0] == "<" and len(each) == 3: tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( z3.Implies( history1(i) == history2(i), z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, history1(x) == history2(x)), # z3.Not(tick2(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, history1(x) == history2(x)), z3.Not(tick2(x))))) elif each[0] == "<" and len(each) == 4: tick1 = self.tickDict["t_%s" % (each[1])] delay = each[2] tick2 = self.tickDict["t_%s" % (each[3])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( z3.Implies( history2(i) - history1(i) == delay, z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, history2(x) - history1(x) == delay), # z3.Not(tick2(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, history2(x) - history1(x) == delay), z3.Not(tick2(x))))) elif each[0] == "≤": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add(history1(i) >= history2(i)) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) >= history2(x)))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, history1(x) >= history2(x)))) elif each[0] == "⊆": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add(z3.Implies(tick1(i), tick2(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n, tick1(x)), # tick2(x)))) else: self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x >= 1, tick1(x)), tick2(x)))) elif each[0] == "#": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add( z3.Or(z3.Not(tick1(i)), z3.Not(tick2(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # z3.Or(z3.Not(tick1(x)), z3.Not(tick2(x)))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, z3.Or(z3.Not(tick1(x)), z3.Not(tick2(x)))))) elif each[0] == "+": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add(tick1(i) == z3.Or(tick2(i), tick3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # tick1(x) == z3.Or(tick2(x), tick3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, tick1(x) == z3.Or(tick2(x), tick3(x))))) elif each[0] == "*": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 1): self.solver.add( z3.Implies(tick1(i), z3.And(tick2(i), tick3(i)))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n), # tick1(x) == z3.And(tick2(x), tick3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies(x >= 1, tick1(x) == z3.And(tick2(x), tick3(x))))) elif each[0] == "∧": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) >= history3(i), history2(i), history3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) >= history3(x),history2(x),history3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) >= history3(x), history2(x), history3(x))))) elif each[0] == "∨": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) <= history3(i), history2(i), history3(i))) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) <= history3(x), history2(x), history3(x))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) <= history3(x), history2(x), history3(x))))) elif each[0] == "$": history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] delay = z3.IntVal(int(each[3])) x = z3.Int("x") if self.bound > 0: for i in range(1, self.bound + 2): self.solver.add( history1(i) == z3.If( history2(i) >= delay, history2(i) - delay, 0)) # self.solver.add(z3.ForAll(x, z3.Implies( # z3.And(x >= 1, x <= self.n + 1), # history1(x) == z3.If(history2(x) >= delay,history2(x) - delay,0)))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 1, history1(x) == z3.If( history2(x) >= delay, history2(x) - delay, 0)))) elif each[0] == "on": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[4])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[4])] self.addTickStep(each[1]) self.addTickStep(each[2]) self.addTickStep(each[4]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep2 = self.tickStep["s_%s" % (each[2])] tickStep3 = self.tickStep["s_%s" % (each[4])] x = z3.Int("x") if self.bound > 0: for i in range(1, int(each[3]) + 1): self.solver.add(z3.Not(tick1(i))) for i in range(int(each[3]) + 1, self.bound + 1): t = [] for j in range(1, i - int(each[3]) + 1): t.append( z3.And( tick2(j), history3(i) - history3(j) == int(each[3]))) self.solver.add(z3.And(tick3(i), z3.Or(t)) == tick1(i)) self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x > 0, x <= self.n + 1), history2(x) >= history1(x)))) self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x > 0, x <= self.n, tick1(x)), tick3(x)))) # self.solver.add( # z3.ForAll(x, z3.Implies( # z3.And(x > 0, x <= history1(self.bound + 1)), # history3(tickStep2(x)) - history3(tickStep1(x)) == int(each[3]) # ))) # for i in range(self.bound + 1): # self.solver.add(history2(i) >= history1(i)) # for i in range(self.bound): # self.solver.add( # z3.Implies( # tick1(i), tick3(i) # ) # ) # for i in range(self.bound + 1): # self.solver.add( # history3(tickStep1(i)) - history3(tickStep2(i)) == int(each[3]) # ) # self.solver.add(z3.ForAll(x, z3.And( # z3.Implies(z3.And(x >= 1, x <= history1(self.bound + 1),tick2(x)), # tick1(tickStep3(history3(x) + int(each[3]))) # )))) else: self.solver.add( z3.ForAll( x, z3.And( z3.Implies(x >= 1, history2(x) >= history1(x))))) self.solver.add( z3.ForAll( x, z3.And( z3.Implies(z3.And(x >= 1, tick1(x)), tick3(x))))) self.solver.add( z3.ForAll( x, z3.And( z3.Implies(x >= 1, (history3(tickStep1(x)) - history3(tickStep2(x)) == int(each[3])))))) elif each[0] == "∝": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] x = z3.Int("x") left = tick1(x) if is_number(each[3]): k = z3.Int("k_%s" % (cnt)) self.solver.add(k >= 0, k < int(each[3])) right = z3.And(tick2(x), history2(x) >= 0, (history2(x) + k) % z3.IntVal(each[3]) == 0) cnt += 1 # right = z3.And(tick2(x), history2(x) > 0, (history2(x)) % z3.IntVal(each[3]) == 0) else: period = z3.Int("%s" % each[3]) tmp = self.parameter[each[3]] self.printParameter[each[3]] = period k = z3.Int("k_%s" % (cnt)) self.solver.add(k >= 0, k < period) right = z3.And(tick2(x), history2(x) >= 0, (history2(x) + k) % period == 0) self.solver.add(period >= int(tmp[2])) self.solver.add(period <= int(tmp[3])) cnt += 1 if self.bound > 0: self.solver.add( z3.ForAll( x, z3.And( z3.Implies(z3.And(x >= 1, x <= self.n), left == right)))) else: self.solver.add( z3.ForAll(x, z3.And(z3.Implies(x >= 1, left == right)))) elif each[0] == "☇": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] tick3 = self.tickDict["t_%s" % (each[3])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] history3 = self.historyDict["h_%s" % (each[3])] self.addTickStep(each[1]) self.addTickStep(each[3]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep3 = self.tickStep["s_%s" % (each[3])] x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 2, x <= history3(self.bound + 1)), tick1(tickStep1(x)) == ( history2(tickStep3(x)) - history2(tickStep3(x - 1)) >= 1)))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 2, z3.And( tick1(tickStep1(x)), history2(tickStep3(x)) - history2(tickStep3(x - 1)) >= 1)))) elif each[0] == "==": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies(z3.And(x >= 1, x <= self.n), tick1(x) == tick2(x)))) else: self.solver.add( z3.ForAll(x, z3.Implies(x >= 1, tick1(x) == tick2(x)))) elif each[0] == "⋈±": tick1 = self.tickDict["t_%s" % (each[1])] tick2 = self.tickDict["t_%s" % (each[2])] history1 = self.historyDict["h_%s" % (each[1])] history2 = self.historyDict["h_%s" % (each[2])] self.addTickStep(each[1]) self.addTickStep(each[2]) tickStep1 = self.tickStep["s_%s" % (each[1])] tickStep2 = self.tickStep["s_%s" % (each[2])] lower = int(each[3]) - int(each[4]) upper = int(each[3]) + int(each[4]) x = z3.Int("x") if self.bound > 0: self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 1, x <= self.bound + 1, tick1(x)), history1(tickStep2(history2(x) + upper)) - history1( tickStep2(history2(x) + lower)) == 1))) self.solver.add( z3.ForAll( x, z3.Implies( z3.And(x >= 2, x <= history1(self.bound + 1)), z3.And( (history2(tickStep1(x)) - history2(tickStep1(x - 1)) >= lower), (history2(tickStep1(x)) - history2(tickStep1(x - 1)) <= upper))))) else: self.solver.add( z3.ForAll( x, z3.Implies( x >= 2, z3.And( (history2(tickStep1(x)) - history2(tickStep1(x - 1)) >= lower), (history2(tickStep1(x)) - history2(tickStep1(x - 1)) <= upper)))))