def CALLDATACOPY(self, gstate, dest_offset, offset, length): length_concrete = svm_utils.is_bv_concrete(length) if not length_concrete: logging.warning('Symbolic calldata size') length = z3.BitVecVal(64, 256) if gstate.environment.calldata_type == CalldataType.UNDEFINED: length = svm_utils.get_concrete_int(length) if svm_utils.is_bv_concrete(offset): offset = svm_utils.get_concrete_int(offset) for i in range(length): data_word = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATA, gstate.wstate.gen, index=offset+(i//32)) slot = i % 32 data_bytes = svm_utils.split_bv_into_bytes(data_word) data = data_bytes[slot] gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, data) else: for i in range(length): data = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.CALLDATA, gstate.wstate.gen, unique=True, bv_size=8) gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, data) elif gstate.environment.calldata_type == CalldataType.DEFINED: length = svm_utils.get_concrete_int(length) offset_concrete = svm_utils.is_bv_concrete(offset) calldata_bytes = svm_utils.split_bv_into_bytes(gstate.environment.calldata) offset_concrete = svm_utils.is_bv_concrete(offset) for i in range(length): gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, calldata_bytes[offset_concrete+i]) else: raise SVMRuntimeError('Unknown calldata type')
def opcode_return_data_copy(returndata, memory, target_memory, return_offset, return_length=32): if not is_z3_express(return_length): for i in range(format_to_int(return_length)): index = opcode_add(return_length, i) pos = opcode_add(target_memory, i) memory = z3.Store(memory, pos, returndata[index]) return z3.simplify(memory) for i in range(opcode_memory.LENGTH): check_write_express = z3.And(i >= target_memory, i < target_memory + return_length) pos = z3.If(check_write_express, return_offset + i - target_memory, -1) check_get_calldata = z3.If(pos > opcode_call_data_config.LENGTH, 0, returndata[pos]) get_data = z3.If(check_write_express, check_get_calldata, memory[i]) memory = z3.Store(memory, i, get_data) return z3.simplify(memory)
def ConditionalStore(self, index, value, cond): if isinstance(index, int): index = BVV(index, self.index_width) else: assert index.size == self.index_width if isinstance(value, int): value = BVV(value, self.value_width) else: assert value.size == self.value_width if isinstance(cond, bool): cond = BoolV(cond) if isinstance(cond, BoolV): if cond.value: self.Store(index, value) return if (self._conc_store is not None and isinstance(index, BVV) and index.value in self._conc_store and self._conc_store[index.value].eq(value)): # the condition is symbolic, but the value is already in memory # we can safetely skip the store return self._switch_to_symbolic() self._z3obj = z3.If(cond.z3obj, z3.Store(self._z3obj, index.z3obj, value.z3obj), self._z3obj) # this can be quite inefficient. # Let's try to simplfy the expression. self._z3obj = z3.simplify(self._z3obj)
def getEq(self, mvars): r = [] #print self.src, self.dst if (self.src.isReg()): src = self.src.name # self.src.size = self.size # srcs = self.getOperands([self.src]) # print srcs else: assert (0) old_sname, new_sname, offset = Memvars.write(self.dst) old_array = mkArray(old_sname) array = mkArray(new_sname) for i in range(self.size): dst_op = Operand(self.dst.mem_source + "@" + str(offset + i), "BYTE") src_var = z3.BitVec(src + ":" + str(i) + "(0)", 8) if (dst_op in mvars): array = z3.Store(array, offset + i, src_var) r.append(src_var <> 0) r.append((old_array == array)) return r
def getEq(self): src = self.read_operands[0] if src.isVar(): srcs = mkByteListVar(src) else: srcs = mkByteListConst(src) #endianness srcs.reverse() dst = self.write_operands[0] dsts = dst.getLocations() conds = [] old_sname, new_sname = Memvars.write(dsts[0]) #array = mkArray(old_sname) #new_array = mkArray(new_sname) old_array = mkArray(old_sname) array = mkArray(new_sname) for (src, dst) in zip(srcs, dsts): array = z3.Store(array, dst.getIndex(), src) conds = [(old_array == array)] return conds
def getEq(self): src = (self.read_operands)[0] if src.isVar(): srcs = map(lambda b: z3.BitVec(b, 8), src.get_bytes()) else: srcs = map(lambda b: z3.BitVecVal(int(b, 16), 8), src.get_bytes()) srcs.reverse() conds = [] offset = Memvars.getOffset(self.write_operands[0]) old_sname, new_sname, offset = Memvars.write(self.write_operands[0]) old_array = mkArray(old_sname) array = mkArray(new_sname) #for (i,src) in zip(range(offset,offset-(src.size),-1), srcs): #for (i,src) in zip(range(offset,offset+(src.size)+1), srcs): for (i, src) in zip(range(src.size), srcs): array = z3.Store(array, offset + i, src) conds = [(old_array == array)] return conds
def getEq(self, mlocs): src = InputOp("stdin", 1) src.size_in_bytes = self.size srcs = mkByteListVar(src) dst = self.dst #self.func.write_operands[0] dsts = dst.getLocations() conds = [] old_sname, new_sname = Memvars.write(dsts[0]) #array = mkArray(old_sname) #new_array = mkArray(new_sname) old_array = mkArray(old_sname) array = mkArray(new_sname) for (src, dst) in zip(srcs, dsts): if dst in mlocs: array = z3.Store(array, dst.getIndex(), src) conds.append(src <> 10) conds.append(src <> 0) conds.append((old_array == array)) return conds
def Store(self, index, value): if isinstance(index, int): index = BVV(index, self.index_width) else: assert index.size == self.index_width if isinstance(value, int): value = BVV(value, self.value_width) else: assert value.size == self.value_width # invalidate cache self._z3objConcCache = None if ( isinstance(index, BVV) and self._conc_store is not None ): # concrete mode self._conc_store[index.value] = value else: # symbolic mode self._switch_to_symbolic() self._z3obj = z3.Store( self._z3obj, index.z3obj, value.z3obj )
def RETURNDATACOPY(self, gstate, dest_offset, offset, length): offset = svm_utils.get_concrete_int(offset) length = svm_utils.get_concrete_int(length) if length == 0: return return_data_bytes = svm_utils.split_bv_into_bytes(gstate.return_data) for i in range(length): gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, return_data_bytes[offset+i])
def MSTORE(self, gstate, index, value): if isinstance(value, z3.BoolRef): value = z3.If(value, z3.BitVecVal(1, 256), z3.BitVecVal(0, 256)) value_bytes = svm_utils.split_bv_into_bytes(value) for i in range(32): if svm_utils.is_bv_concrete(index): gstate.mstate.memory_dict[svm_utils.get_concrete_int(index)+i] = value_bytes[i] gstate.mstate.memory = z3.Store(gstate.mstate.memory, index+i, value_bytes[i])
def overlay(self, chunk, base_off, chunk_off, length): slen = z3.simplify(length) if z3.is_bv_value(slen): for i in range(slen.as_long()): if isinstance(chunk, Memory): sel = chunk.select(chunk_off + i) else: sel = z3.Select(chunk, chunk_off + i) self._mem = z3.Store(self._mem, base_off + i, sel) else: if self._idx is None: self._idx = z3.BitVec('idx', 256) if isinstance(chunk, Memory): chunk_val = chunk.select(self._idx - base_off + chunk_off) else: chunk_val = z3.Select(chunk, self._idx - base_off + chunk_off) self._mem = z3.If( z3.And(self._idx >= base_off, self._idx < base_off + length), z3.Store(state.MemoryEmpty, self._idx, chunk_val), self._mem)
def z3_set_memory(memory, address, value, arch): size = value.size() num_bytes = size/8 new_memory = memory for i in range(0, num_bytes): if arch.memory_endness == 'Iend_LE': upper = ((i + 1) * 8) - 1 else: upper = ((num_bytes - i) * 8) - 1 new_memory = z3.Store(new_memory, address + i, z3.Extract(upper, upper - 7, value)) return new_memory
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 f2(): a, b, c, d = z3.BitVecs('a b c d', 3) # 4 bitvectors variable tuple = z3.Datatype('tuple') # new data type 'tuple' tuple.declare( 'tuple', ('f1', z3.BitVecSort(3)), ('f2', z3.BitVecSort(3))) # f1, f2 are for accessing element in tuples tuple = tuple.create() tuple1 = tuple.tuple(a, b) # tuple1 -> (a, b) tuple2 = tuple.tuple(b, c) # tuple2 -> (b, c) tuple1_f2 = tuple.f2(tuple1) # a #tuple1_f2 = tuple.f2(tuple1) # b tuple2_f1 = tuple.f1(tuple2) # c print(tuple1_f2, tuple2_f1) if (tuple1_f2 == tuple2_f1): print("hi") arr0 = z3.K(tuple, False) # arr0 -> arr0[tuple] = false arr1 = z3.Store(arr0, tuple1, True) # arr1 -> arr0[tuple1] = true arr2 = z3.Store(arr1, tuple2, True) # arr -> arr0[tuple2] = true print(arr0) print(arr1) print(arr2) #print(arr1[tuple1]) #print(arr2[tuple2]) #print(arr0) #print(arr1) #print(arr2) s = z3.Solver() s.add(tuple1_f1 == tuple2_f2) # a = c s.add(tuple1_f1 == tuple1_f2) # a = b
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 get_z3_equality_list(stmt_node, z3_vars, direct_equality= False): global all_z3_vars z3_asserts = [] if not direct_equality: stmt_node = stmt_node.children[0] ## get the equalitystmt first left = stmt_node.children[0] right = stmt_node.children[1] zright = get_z3_expr(right, z3_vars) name = "stmt_rhs_{}".format(stmt_node.line) i = 0 temp_name = name while (temp_name in all_z3_vars): temp_name = name + "_" + str(i) i += 1 name = temp_name zright_temp = z3.Int(name) z3_asserts.append(zright_temp == zright) all_z3_vars[name] = zright_temp if left.data == "select": # we need to update the z3_vars array_name = left.children[0].children[0].value current_label = z3_vars[array_name][1] current_array = z3_vars[array_name][0] new_label = current_label + 1 new_name = "{}_{}".format(array_name, new_label) new_array = z3.Array(new_name, z3.IntSort(), z3.IntSort()) all_z3_vars[new_name] = new_array if (left.children[1].data == "var"): index = z3_vars[left.children[1].children[0].value][0] else: #left children is num index = left.children[1].children[0].value store = z3.Store(current_array, index, zright_temp) z3_vars[array_name] = (new_array, new_label) z3_asserts.append(new_array == store) #LHS equal to new variable if left.data == "var": var_name = left.children[0].value var_label = z3_vars[var_name][1] new_name = "{}_{}".format(var_name, var_label+1) new_var = z3.Int(new_name) all_z3_vars[new_name] = new_var # add the new variable to global list z3_vars[var_name] = (new_var, var_label + 1) z3_asserts.append(new_var == zright_temp) return [(assertion, stmt_node) for assertion in z3_asserts]
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 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 main(): b, c = z3.Ints("b c") a = z3.Array("a", z3.IntSort(), z3.IntSort()) f = z3.Function("f", z3.IntSort(), z3.IntSort()) solver = z3.Solver() solver.add(c == b + z3.IntVal(2)) lhs = f(z3.Store(a, b, 3)[c - 2]) rhs = f(c - b + 1) solver.add(lhs != rhs) res = solver.check() if res == z3.sat: print("sat") elif res == z3.unsat: print("unsat") else: print("unknown")
def main(): b, c = z3.Ints('b c') a = z3.Array('a', z3.IntSort(), z3.IntSort()) f = z3.Function('f', z3.IntSort(), z3.IntSort()) solver = z3.Solver() solver.add(c == b + z3.IntVal(2)) lhs = f(z3.Store(a, b, 3)[c - 2]) rhs = f(c - b + 1) solver.add(lhs <> rhs) res = solver.check() if res == z3.sat: print 'sat' elif res == z3.unsat: print 'unsat' else: print 'unknown'
def CODECOPY(self, gstate, dest_offset, offset, length): active_address = gstate.environment.active_address active_account = gstate.wstate.address_to_account[active_address] offset = svm_utils.get_concrete_int(offset) if svm_utils.is_bv_concrete(length): length = svm_utils.get_concrete_int(length) else: length = 0 assert isinstance(gstate.environment.runtime_bytecode_bytes, list) bytecode_bytes = gstate.environment.runtime_bytecode_bytes for i in range(length): if offset + i < len(bytecode_bytes): data_byte = bytecode_bytes[offset+i] else: data_byte = z3.BitVecVal(0, 8) gstate.mstate.memory = z3.Store(gstate.mstate.memory, dest_offset+i, data_byte) gstate.mstate.memory_dict[svm_utils.get_concrete_int(dest_offset+i)] = data_byte
def proc_apply(self, expr, state): f = self.context.reduce(expr['func']) args = expr['args'] if f['what'] == 'expr:special': if f['id'] == 'gmap_lookup': state, k = self.proc(args[0], state) state, m = self.proc(args[1], state) return state, m[k] elif f['id'] == 'map_insert': state, k = self.proc(args[0], state) state, v = self.proc(args[1], state) state, m = self.proc(args[2], state) rangesort = m.range() vsome = constructor_by_name(rangesort, "Some")(v) return state, z3.Store(m, k, vsome) elif f['id'] == 'len_buf': state, buf = self.proc(args[0], state) return state, z3.Int2BV(z3.Length(buf), 64) elif f['id'] == 'resize_buf': state, newlen = self.proc(args[0], state) state, buf = self.proc(args[1], state) ## XXX should be of length newlen, not empty.. return state, z3.Empty(buf.sort()) elif f['id'] == 'uint64_gt': state, a0 = self.proc(args[0], state) state, a1 = self.proc(args[1], state) return state, z3.If(a0 > a1, self.bool_sort.constructor(0)(), self.bool_sort.constructor(1)()) elif f['id'] == 'eqDec_time': state, a0 = self.proc(args[0], state) state, a1 = self.proc(args[1], state) return state, z3.If(a0 == a1, self.sumbool_sort.constructor(0)(), self.sumbool_sort.constructor(1)()) else: raise Exception('unknown special function', f['id']) else: print expr raise Exception('unknown apply on', f['what'])
def mk_eqs_from_model(m, consts, model_completion=False): eqs = [] for const in consts: # treat arrays specially due to the else_value sort = const.sort() if isinstance(sort, z3.ArraySortRef): val_interp = m[const] if (val_interp is not None) and isinstance(val_interp, z3.FuncInterp): idx_sort = sort.domain() val_sort = sort.range() val = z3.K(val_sort, val_interp.else_value()) for i in range(val_interp.num_entries()): entry = val_interp.entry(i) val = z3.Store(val, entry.arg_value(0), entry.value()) else: val = m.eval(const, model_completion=model_completion) else: val = m.eval(const, model_completion=model_completion) eqs.append(const == val) return eqs
def opcode_write_memory(memory, offset, data, length=32): parts = [] if not is_z3_express(length): length = format_to_int(length) for i in range(length): index = opcode_add(offset, i) if type(data) == list: write_data = z3.BitVecVal(data[i], 8) else: high = (length - i) * 8 - 1 low = high - 7 write_data = z3.Extract(high, low, data) memory = z3.Store(memory, index, write_data) return z3.simplify(memory) print length exit() return z3.Concat(parts)
def getEq(self, mvars): r = [] old_sname, new_sname, offset = Memvars.write(self.dst) old_array = mkArray(old_sname) array = mkArray(new_sname) for i in range(self.size): op = Operand(self.dst.mem_source + "@" + str(offset + i), "BYTE") if (op in mvars): array = z3.Store(array, offset + i, z3.BitVec("stdin:" + str(i) + "(0)", 8)) r.append(z3.BitVec("stdin:" + str(i) + "(0)", 8) <> 10) r.append(z3.BitVec("stdin:" + str(i) + "(0)", 8) <> 0) r.append((old_array == array)) return r
def __setitem__(self, key: BitVec, value: BitVec) -> None: """Sets an item in the array, key can be symbolic.""" if isinstance(value, Bool): value = If(value, 1, 0) self.raw = z3.Store(self.raw, key.raw, value.raw) # type: ignore
def mem_from_str(text, base=symevm.state.MemoryEmpty): b = symevm.util.hex_to_bytes(text) m = base for i, v in enumerate(b): m = z3.Store(m, z3.BitVecVal(i, 256), z3.BitVecVal(v, 8)) return symevm.mem.Memory(base=m), len(b)
def proc_apply(self, expr, state): f = self.context.reduce(expr['func']) args = expr['args'] if f['what'] == 'expr:special': # for converting Z to u32 if f['id'] == 'u3' or f['id'] == 'u2': arg = args[0] # be able to distinguish between Z->u32 and Z->u64 if f['id'] == 'u3': arg['name'] = 'u32' else: arg['name'] = 'u64' state, val = self.proc(arg, state) return state, z3.Const(anon(), val) elif f['id'] == 'gtb': arg0 = args[0]['cases'][0]['body']['args'][0] nstate, arg1 = self.proc( args[1]['cases'][0]['body']['args'][0], state) return nstate, z3.If(arg0 > arg1, self.bool_sort.constructor(0)(), self.bool_sort.constructor(1)()) elif f['id'] == 'gmap_lookup': state, k = self.proc(args[0], state) state, m = self.proc(args[1], state) return state, m[k] elif f['id'] == 'map_insert': state, k = self.proc(args[0], state) state, v = self.proc(args[1], state) state, m = self.proc(args[2], state) rangesort = m.range() vsome = constructor_by_name(rangesort, "Some")(v) return state, z3.Store(m, k, vsome) elif f['id'] == 'reads': return state, state elif f['id'] == 'modify': _, newstate = self.proc(args[0]['body'], state) return newstate, self.unit_tt elif f['id'] == 'ret': state, res = self.proc(args[0], state) return state, res elif f['id'] == 'len_buf': state, buf = self.proc(args[0], state) return state, z3.Int2BV(z3.Length(buf), 64) elif f['id'] == 'resize_buf': state, newlen = self.proc(args[0], state) state, buf = self.proc(args[1], state) ## XXX should be of length newlen, not empty.. return state, z3.Empty(buf.sort()) elif f['id'] == 'eqDec_time': state, a0 = self.proc(args[0], state) state, a1 = self.proc(args[1], state) return state, z3.If(a0 == a1, self.sumbool_sort.constructor(0)(), self.sumbool_sort.constructor(1)()) elif f['id'] == 'time_ge': state, a0 = self.proc(args[0], state) state, a1 = self.proc(args[1], state) # constructor 0 is true, 1 is false return state, z3.If(a0 >= a1, self.bool_sort.constructor(0)(), self.bool_sort.constructor(1)()) elif f['id'] == 'symAssert': state, a = self.proc(args[0], state) return state, z3.And(a == self.bool_sort.constructor(0)()) else: raise Exception('unknown special function', f['id']) else: raise Exception('unknown apply on', f['what'])
def VertexOperationToSmt(self): assert (self.type != VertexNode.VertexType.NONE) if self.type == VertexNode.VertexType.VAR: # Possible Vertex : input Variable, name = operand1 # input variable: there is nothing to do. # assigned Variable: name = operands[0] # It's an input variable if there is no operand : if self.operands == None: return None # otherwise, it's an assigned variable, but make sure just in case assert (self.operator == VertexNode.OpCode.ASSIGN) return self.VertexNameToSmt() == self.operands[0].VertexNameToSmt() elif self.type == VertexNode.VertexType.TEMP: # Possible Vertex : Function Call, Array Load, Binary Operation, Comparison, # Conditional Assignment, Unary Operation # function call: name = func_name(arguments) # array load: name = array[index] # binary operation: name = operand1 op operand2 # comparison: name = operand1 comp operand2 # conditional assignment: name = ite(operand1, operand2, operand3) # unary operation: name = op operand1 # It's a function call if self.operator == VertexNode.OpCode.FUNCCALL: assert (self.operands[0].type == VertexNode.VertexType.FUNC) # There are four possible functions that can last until now: if self.operands[0].name == "merge": args = [] for op in self.operands[1:]: args.append(op.VertexNameToSmt()) return self.VertexNameToSmt() == z3.Concat(args) elif self.operands[0].name == "split": toSplit = self.operands[1].VertexNameToSmt() # Extract requires actual numerical value. lowerBound = self.operands[2].value upperBound = self.operands[3].value return self.VertexNameToSmt() == z3.Extract( upperBound, lowerBound, toSplit) elif self.operands[0].name == "zeroext": toExtend = self.operands[1].VertexNameToSmt() # ZeroExt requires actual numerical value n = self.operands[2].value return self.VertexNameToSmt() == z3.ZeroExt(n, toExtend) elif self.operands[0].name == "concat": args = [] for op in self.operands[1:]: args.append(op.VertexNameToSmt()) return self.VertexNameToSmt() == z3.Concat(args) # It's an array load elif self.operator == VertexNode.OpCode.LOAD: array = self.operands[0].VertexNameToSmt() arrayIndex = self.operands[1].VertexNameToSmt() return self.VertexNameToSmt() == z3.Select(array, arrayIndex) # It's a conditional statement elif self.operator == VertexNode.OpCode.CONDITIONAL: cond = self.operands[0].VertexNameToSmt() truePath = self.operands[1].VertexNameToSmt() falsePath = self.operands[2].VertexNameToSmt() return self.VertexNameToSmt() == z3.If(cond, truePath, falsePath) # It's a comparison (x < y) elif VertexNode.OpCode.IsComparison(self.operator): lhs = self.operands[0].VertexNameToSmt() rhs = self.operands[1].VertexNameToSmt() if self.operator == VertexNode.OpCode.GT: return self.VertexNameToSmt() == z3.UGT(lhs, rhs) elif self.operator == VertexNode.OpCode.GE: return self.VertexNameToSmt() == z3.UGE(lhs, rhs) elif self.operator == VertexNode.OpCode.LT: return self.VertexNameToSmt() == z3.ULT(lhs, rhs) elif self.operator == VertexNode.OpCode.LE: return self.VertexNameToSmt() == z3.ULE(lhs, rhs) elif self.operator == VertexNode.OpCode.EQ: return self.VertexNameToSmt() == (lhs == rhs) elif self.operator == VertexNode.OpCode.NE: return self.VertexNameToSmt() == (lhs != rhs) # It's a binary operation elif VertexNode.OpCode.IsBinaryOp(self.operator): lhs = self.operands[0].VertexNameToSmt() rhs = self.operands[1].VertexNameToSmt() if self.operator == VertexNode.OpCode.PLUS: return self.VertexNameToSmt() == (lhs + rhs) elif self.operator == VertexNode.OpCode.MINUS: return self.VertexNameToSmt() == (lhs - rhs) elif self.operator == VertexNode.OpCode.AND: return self.VertexNameToSmt() == (lhs & rhs) elif self.operator == VertexNode.OpCode.OR: return self.VertexNameToSmt() == (lhs | rhs) elif self.operator == VertexNode.OpCode.XOR: return self.VertexNameToSmt() == (lhs ^ rhs) elif self.operator == VertexNode.OpCode.SHL: return self.VertexNameToSmt() == (lhs << rhs) elif self.operator == VertexNode.OpCode.SHR: return self.VertexNameToSmt() == (z3.LShR(lhs, rhs)) elif self.operator == VertexNode.OpCode.ROL: return self.VertexNameToSmt() == (z3.RotateLeft(lhs, rhs)) elif self.operator == VertexNode.OpCode.ROR: return self.VertexNameToSmt() == (z3.RotateRight(lhs, rhs)) elif self.operator == VertexNode.OpCode.MUL: return self.VertexNameToSmt() == (lhs * rhs) elif self.operator == VertexNnode.OpCode.DIV: return self.VertexNameToSmt() == (lhs / rhs) # It's a unary operation elif VertexNode.OpCode.IsUnaryOp(self.operator): rhs = self.operands[0].VertexNameToSmt() if self.operator == VertexNode.OpCode.NOT: return self.VertexNameToSmt() == ~rhs elif self.type == VertexNode.VertexType.IMM: # Possible Vertex : Immediate Value return None elif self.type == VertexNode.VertexType.ARR: # Possible Vertex : Input array, array store # input array: there is nothing to do # array store: newarray = store(array, index, value) # if operator == None, it's an "input" array if self.operator == None: return None if self.operator == VertexNode.OpCode.NONE: return None # Otherwise, it must be an array store operation vertex assert (self.operator == VertexNode.OpCode.STORE) oldArray = self.operands[0].VertexNameToSmt() index = self.operands[1].VertexNameToSmt() value = self.operands[2].VertexNameToSmt() newArray = self.VertexNameToSmt() return newArray == z3.Store(oldArray, index, value) elif self.type == VertexNode.VertexType.FUNC: # Possible Vertex : Name of the function return None
def opcode_init_memory(memory, length): for i in range(length): memory = z3.Store(memory, i, z3.BitVecVal(0, 8)) return z3.simplify(memory)