Example #1
0
    def _min(self,
             expr,
             extra_constraints=(),
             solver=None,
             model_callback=None):
        global solve_count

        lo = 0
        hi = 2**expr.size() - 1
        vals = set()

        numpop = 0
        if len(extra_constraints) > 0:
            solver.push()
            numpop += 1
            solver.add(*[self.convert(e) for e in extra_constraints])

        # TODO: Can only deal with bitvectors, not floats
        while hi - lo > 1:
            middle = (lo + hi) // 2
            #l.debug("h/m/l/d: %d %d %d %d", hi, middle, lo, hi-lo)

            solver.push()
            solver.add(z3.UGE(expr, lo), z3.ULE(expr, middle))
            numpop += 1

            solve_count += 1
            l.debug("Doing a check!")
            if solver.check() == z3.sat:
                l.debug("... still sat")
                if model_callback is not None:
                    model_callback(self._generic_model(solver.model()))
                vals.add(self._primitive_from_model(solver.model(), expr))
                hi = middle
            else:
                l.debug("... now unsat")
                lo = middle
                solver.pop()
                numpop -= 1

        for _ in range(numpop):
            solver.pop()

        #l.debug("final hi/lo: %d, %d", hi, lo)

        if hi == lo: return lo
        else:
            solver.push()
            solver.add(expr == lo)
            l.debug("Doing a check!")
            if solver.check() == z3.sat:
                if model_callback is not None:
                    model_callback(self._generic_model(solver.model()))
                vals.add(lo)
                solver.pop()
            else:
                vals.add(hi)
                solver.pop()

        return min(vals)
Example #2
0
 def UGE(self, other):
     if isinstance(other, int):
         other = BVV(other, self.size)
     else:
         assert isinstance(other, BV)
         assert self.size == other.size
     return BoolExpr(z3.UGE(self.z3obj, other.z3obj))
Example #3
0
def UGE(a: BitVec, b: BitVec) -> Bool:
    """Create an unsigned greater or equals expression.

    :param a:
    :param b:
    :return:
    """
    annotations = a.annotations + b.annotations
    return Bool(z3.UGE(a.raw, b.raw), annotations)
Example #4
0
    def _min_values(self,
                    expr,
                    extra_constraints=(),
                    result=None,
                    solver=None):
        global solve_count

        lo = 0
        hi = 2**expr.size() - 1
        vals = set()

        numpop = 0
        if len(extra_constraints) > 0:
            solver.push()
            numpop += 1
            solver.add(*[self.convert(e) for e in extra_constraints])

        while hi - lo > 1:
            middle = (lo + hi) / 2
            #l.debug("h/m/l/d: %d %d %d %d", hi, middle, lo, hi-lo)

            solver.push()
            solver.add(z3.UGE(expr, lo), z3.ULE(expr, middle))
            numpop += 1

            solve_count += 1
            l.debug("Doing a check!")
            if solver.check() == z3.sat:
                l.debug("... still sat")
                vals.add(self._primitive_from_model(solver.model(), expr))
                hi = middle
            else:
                l.debug("... now unsat")
                lo = middle
                solver.pop()
                numpop -= 1

        for _ in range(numpop):
            solver.pop()

        #l.debug("final hi/lo: %d, %d", hi, lo)

        if hi == lo: return lo
        else:
            solver.push()
            solver.add(expr == lo)
            l.debug("Doing a check!")
            if solver.check() == z3.sat:
                vals.add(lo)
                solver.pop()
            else:
                vals.add(hi)
                solver.pop()

        return vals
Example #5
0
    def _touches_address(self, op_name, address):
        "Return a boolean indicating whether `op_name` touches `address`"

        # Check for overflow, which is defined to wrap around
        upper_bound = self.base_address[op_name] + self.width_bytes[op_name]
        overflow = z3.ULT(upper_bound, self.base_address[op_name])

        return z3.If(
            overflow,
            # If overflow, account for wraparound
            z3.Or(
                z3.UGE(address, self.base_address[op_name]),
                z3.ULT(address, upper_bound),
            ),
            # If no overflow, the address should be in [base, base + offset)
            z3.And(
                z3.UGE(address, self.base_address[op_name]),
                z3.ULT(address, upper_bound),
            ),
        )
Example #6
0
            def newf(*args):
                assert len(args) == len(dst_end_args)
                cond = []
                for a, b in zip(args[:-1], dst_start_args[:-1]):
                    cond.append(a == b)

                cond.append(z3.UGE(args[-1], dst_start_args[-1]))
                cond.append(z3.ULE(args[-1], dst_end_args[-1]))

                cond = z3.And(*cond)

                return util.If(cond, z3.BitVecVal(0, write_size), dstfn(*args))
Example #7
0
    def newf(*args):
        assert len(args) == len(dst_end_args)
        cond = []
        for a, b in zip(args[:-1], dst_start_args[:-1]):
            cond.append(a == b)

        cond.append(z3.UGE(args[-1], dst_start_args[-1]))
        cond.append(z3.ULT(args[-1], dst_end_args[-1]))

        cond = z3.And(*cond)

        srcargs = src_start_args[:-1] + [args[-1]]

        return util.If(cond, srcfn(*srcargs), dstfn(*args))
Example #8
0
 def __init__(self, meta, opcode, src1, src2, target):
     self.meta = meta
     self.opcode = opcode
     self.src1 = src1
     self.src2 = src2
     self.target = target
     self.op = {
         "beq": lambda a, b: a == b,
         "bne": lambda a, b: a != b,
         "blt": lambda a, b: a < b,
         "bltu": lambda a, b: z3.ULT(a, b),
         "bge": lambda a, b: a >= b,
         "bgeu": lambda a, b: z3.UGE(a, b),
     }[opcode.lower()]
Example #9
0
def main():
    global dse, todo, current
    sys.setrecursionlimit(2000)  # oof
    # Parse arguments
    parser = Sandbox_Win_x86_64.parser(description="PE sandboxer")
    parser.add_argument("filename", help="PE Filename")
    options = parser.parse_args()
    options.dependencies = True  # So we dont need to reimplement qt
    sb = Sandbox_Win_x86_64(LocationDB(),
                            options.filename,
                            options,
                            custom_methods=qt_methods)
    sb.jitter.add_breakpoint(end_ptr, stop_exec)  # End condition
    # Setup the qt string memory and a pointer to it
    sb.jitter.vm.add_memory_page(0x10000018, PAGE_READ | PAGE_WRITE,
                                 pck64(0x20000000))  # Hooking in here
    sb.jitter.vm.add_memory_page(0x20000000, PAGE_READ | PAGE_WRITE,
                                 qtstring)  # The initial qstring
    sb.jitter.vm.add_memory_page(0x10000020, PAGE_READ | PAGE_WRITE,
                                 b'\x00')  # The result
    sb.jitter.cpu.R15 = 0x10000000
    sb.jitter.cpu.RSP = sb.jitter.stack_base + 0x8000
    # Setup and attach the DSE
    dse = DSEPC(sb.machine,
                sb.loc_db,
                produce_solution=DSEPC.PRODUCE_SOLUTION_PATH_COV)
    sb.jitter.init_run(0x140004B61)
    dse.attach(sb.jitter)
    dse.update_state_from_concrete()
    dse.symbolize_memory(interval([(flag_ptr, flag_ptr + 0x20)]))
    # Printable unicode only
    for address in range(flag_ptr, flag_ptr + 0x20, 0x2):
        z3_mem = dse.z3_trans.from_expr(
            dse.eval_expr(ExprMem(ExprInt(address, 64), 16)))
        unicode_constraint = z3.And( \
                                z3.UGE(z3_mem, dse.z3_trans.from_expr(ExprInt(0x0020, 16))), \
                                z3.ULE(z3_mem, dse.z3_trans.from_expr(ExprInt(0x007E, 16))) \
                                )
        dse.cur_solver.add(unicode_constraint)
    snapshot = dse.take_snapshot()
    # Begin run
    todo = [b'\x41\x00' * 0x10]
    while todo:
        dse.restore_snapshot(snapshot)
        current = todo.pop()
        sb.jitter.vm.set_mem(flag_ptr,
                             current)  # Update the password in jitter memory
        print('-' * 40 + f' CONCRETE: {unicode_string(current)}')
        sb.jitter.continue_run()
Example #10
0
 def ComparisonToSmt(self):
     assert (VertexNode.OpCode.IsComparison(self.operator))
     lhs = self.operands[0].VertexNameToSmt()
     rhs = self.operands[1].VertexNameToSmt()
     if self.operator == VertexNode.OpCode.GT:
         return z3.UGT(lhs, rhs)
     elif self.operator == VertexNode.OpCode.GE:
         return z3.UGE(lhs, rhs)
     elif self.operator == VertexNode.OpCode.LT:
         return z3.ULT(lhs, rhs)
     elif self.operator == VertexNode.OpCode.LE:
         return z3.ULE(lhs, rhs)
     elif self.operator == VertexNode.OpCode.EQ:
         return (lhs == rhs)
     elif self.operator == VertexNode.OpCode.NE:
         return (lhs != rhs)
Example #11
0
 def solve_for_memory_access(self, expr_mem, access_type, additional_constraints=set()):
   # Check that input has effect on memory referenced
   if get_expr_ids(expr_mem.ptr) & self.symbolized_mem_ids:
     for possibility in possible_values(expr_mem.ptr):
       address_expr = possibility.value
       access_len = int(expr_mem.size/8)
       # 5 sec timeout
       #self.dse.cur_solver.set('timeout', 5000)
       # Save solver state
       self.dse.cur_solver.push()
       # Add constraints from the expr itself
       for cons in possibility.constraints.union(additional_constraints):
         eaff = cons.to_constraint()
         #print '\tADDING CONSTRAINT: ' + str(eaff)
         self.dse.cur_solver.add(self.dse.z3_trans.from_expr(eaff))
       # Add memory constraints
       for mem_range in self.dse.valid_ranges:
         # Add range constraint
         rc = z3.Not(z3.And(z3.UGE(self.dse.z3_trans.from_expr(address_expr), self.dse.z3_trans.from_expr(mem_range[0])),
                            z3.ULE(self.dse.z3_trans.from_expr(address_expr), self.dse.z3_trans.from_expr(mem_range[1]-ExprInt(access_len-1, 64)))
                           )
                    )
         self.dse.cur_solver.add(rc)
       #print solver
       #import pdb; pdb.set_trace()
       if self.dse.cur_solver.check()==z3.sat:
         model = self.dse.cur_solver.model()
         #import pdb; pdb.set_trace()
         log.debug('SYMB 0x{:08X}: {:s} -> {}AV[{:s}]  '.format(self.dse.jitter.pc, \
                                                         str(model), access_type, \
                                                         str(self.dse.symb.eval_expr(address_expr, eval_cache={})))
                 )
         # Evaluate the buffer that would cause the crash
         crashbuf = self.derive_crashbuf(model)
         # Evaluate the AV adress
         values = self.get_values_from_model(model)
         self.dse.crashes.append(crash( self.dse.jitter.pc, \
                                     self.dse.symb.eval_expr(address_expr, eval_cache=values), \
                                     access_type, \
                                     crashbuf, \
                                     int(self.dse.callsite)
                                   )
                             )
       # Reset the solver
       self.dse.cur_solver.pop()
   return
Example #12
0
    def check(self, instance, conj, is_owner_valid, is_owned1_valid, is_owned2_valid, max_refs, ownerfn=None, ownedby=None):
        """Emit correctness definitions for this refcnt"""

        is_owned_valid = lambda a, b: z3.And(is_owned1_valid(a), is_owned2_valid(b))

        assert ownerfn != None or ownedby != None
        assert not (ownerfn and ownedby)

        if ownerfn:
            ownedby = lambda arg1, arg2: ownerfn(arg2) == arg1

        fn = instance._fields[self._name]
        owner = util.FreshBitVec('owner', self.get_types()[0])
        owned1 = util.FreshBitVec('owned1', self.get_types()[1][0])
        owned2 = util.FreshBitVec('owned2', self.get_types()[1][1])
        idx = util.FreshBitVec('idx', self.get_types()[2])

        ref, perm1, perm2, perm_inv = fn

        # 1) a valid input implies a valid owned output
        conj.append(z3.ForAll([owner, owned1, owned2], z3.Implies(
            z3.And(
                is_owner_valid(owner),
                is_owned_valid(owned1, owned2)),
            z3.ULT(perm_inv(owner, owned1, owned2), max_refs)
        )))

        conj.append(z3.ForAll([owner, idx], z3.Implies(
            z3.And(
                is_owner_valid(owner),
                z3.ULT(idx, max_refs)),
            z3.And(
                is_owned1_valid(perm1(owner, idx)),
                is_owned2_valid(perm2(owner, idx))))))

        # 2) The function function is a bijection
        conj.append(z3.ForAll([owner, owned1, owned2, idx],
            z3.Implies(z3.And(
                is_owner_valid(owner),
                is_owned_valid(owned1, owned2),
                z3.ULT(idx, max_refs)),
            z3.And(
                perm_inv(owner, perm1(owner, idx), perm2(owner, idx)) == idx,
                perm1(owner, perm_inv(owner, owned1, owned2)) == owned1,
                perm2(owner, perm_inv(owner, owned1, owned2)) == owned2,
        ))))

        # 3) if 'owner' owns 'owned', then f(owned) < ref, otherwise w(owned) >= ref
        conj.append(z3.ForAll([owner, owned1, owned2], z3.Implies(
            z3.And(
                is_owner_valid(owner),
                is_owned_valid(owned1, owned2),
            ),
            z3.And(
                z3.Implies(ownedby(owner, (owned1, owned2)),
                    z3.ULT(perm_inv(owner, owned1, owned2), ref(owner))),
                z3.Implies(z3.Not(ownedby(owner, (owned1, owned2))),
                    z3.UGE(perm_inv(owner, owned1, owned2), ref(owner)))
            ))))

        # Checks that the refcnt don't overflows, that if its
        # value is 0 that the owner owns nothing and if its value is max_refs that
        # process owns all the resources.

        # refcount is in the range 0 <= r <= max_refs
        conj.append(z3.ForAll([owner],
            z3.Implies(is_owner_valid(owner), z3.ULE(ref(owner), max_refs))))

        # if refcount is 0, then you own no pages
        conj.append(z3.ForAll([owner, owned1, owned2], z3.Implies(
            z3.And(
                is_owner_valid(owner),
                is_owned_valid(owned1, owned2),
                ref(owner) == z3.BitVecVal(0, self.get_types()[-1]),
            ),
            z3.Not(ownedby(owner, (owned1, owned2))),
        )))

        # if refcount is max_refs, then that owner owns all the resources
        conj.append(z3.ForAll([owner, owned1, owned2], z3.Implies(
            z3.And(
                is_owner_valid(owner),
                is_owned_valid(owned1, owned2),
                ref(owner) == max_refs
            ),
            ownedby(owner, (owned1, owned2)),
        )))
Example #13
0
 def uge(self, other):
     return Bool(z3.UGE(self.symbol, other.symbol))
Example #14
0
from os import cpu_count
from rfb_mc.implementation.eamp.eamp_edge_scheduler import EampEdgeScheduler
from rfb_mc.implementation.eamp.eamp_rfmi_z3 import EampRfmiZ3
from rfb_mc.implementation.multi_processing_integrator_z3 import MultiProcessingIntegratorZ3
from rfb_mc.implementation.runner_z3 import RunnerZ3, FormulaParamsZ3
from rfb_mc.implementation.in_memory_store import InMemoryStore
from rfb_mc.store import StoreData
from rfb_mc.types import Params

RunnerZ3.register_restrictive_formula_module_implementation(EampRfmiZ3)

if __name__ == "__main__":
    k = 18
    x, y, z = z3.BitVecs("x y z", k)
    f = z3.And([
        z3.UGE(x, 0),
        z3.UGE(y, 0),
        z3.URem(x, 4) == 0,
        z3.URem(y, 5) == 0,
        z3.ULT(z, x + y),
    ])

    s2 = perf_counter()
    s = perf_counter()

    a = 100

    store = InMemoryStore(data=StoreData(params=Params(
        bit_width_counter=Counter({k: 2}))))

    print(
Example #15
0
    # This check is done on 32 bits, but the size is not use by Miasm formulas, so
    # it should be OK for any size > 0
    x1 = ExprId("x1", 32)
    x2 = ExprId("x2", 32)
    i1_tmp = ExprInt(1, 1)

    x1_z3 = trans.from_expr(x1)
    x2_z3 = trans.from_expr(x2)
    i1_z3 = trans.from_expr(i1_tmp)

    # (Assumptions, function(arg1, arg2) -> True/False (= i1/i0) to check)
    tests = [
        (x1_z3 == x2_z3, expr_is_equal),
        (x1_z3 != x2_z3, expr_is_not_equal),
        (z3.UGT(x1_z3, x2_z3), expr_is_unsigned_greater),
        (z3.UGE(x1_z3, x2_z3), expr_is_unsigned_greater_or_equal),
        (z3.ULT(x1_z3, x2_z3), expr_is_unsigned_lower),
        (z3.ULE(x1_z3, x2_z3), expr_is_unsigned_lower_or_equal),
        (x1_z3 > x2_z3, expr_is_signed_greater),
        (x1_z3 >= x2_z3, expr_is_signed_greater_or_equal),
        (x1_z3 < x2_z3, expr_is_signed_lower),
        (x1_z3 <= x2_z3, expr_is_signed_lower_or_equal),
    ]

    for assumption, func in tests:
        solver = z3.Solver()
        solver.add(assumption)
        solver.add(trans.from_expr(func(x1, x2)) != i1_z3)
        assert solver.check() == z3.unsat

x = ExprId('x', 32)
Example #16
0
 def uge(self, ctx, return_type, a, atype, b, btype, **kwargs):
     assert atype == btype
     return z3.UGE(a, b)
Example #17
0
 def bvuge(self, other):
     return self.get_family().Bit(z3.UGE(self.value, other.value))
Example #18
0
    things = name.split('[')[1:]
    #    print "things:".format(things)
    if not all(t.endswith(']') for t in things):
        raise SyntaxError()
    return [int(t[:-1]) for t in things]


def is_solver_sort(name):
    return name.startswith('bv[') and name.endswith(']') or name == 'int'


relations_dict = {
    '<': (lambda x, y: z3.ULT(x, y) if z3.is_bv(x) else x < y),
    '<=': (lambda x, y: z3.ULE(x, y) if z3.is_bv(x) else x <= y),
    '>': (lambda x, y: z3.UGT(x, y) if z3.is_bv(x) else x > y),
    '>=': (lambda x, y: z3.UGE(x, y) if z3.is_bv(x) else x >= y),
}


def relations(name):
    return relations_dict.get(name)


functions_dict = {
    "+": (lambda x, y: x + y),
    "-": my_minus,
    "*": (lambda x, y: x * y),
    "concat": (lambda x, y: z3.Concat(x, y)),
}

Example #19
0
    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
Example #20
0
lx12 = z3.Int('lx12')
lx21 = z3.Int('lx21')
lx22 = z3.Int('lx22')
lx31 = z3.Int('lx31')
lx32 = z3.Int('lx32')
lx41 = z3.Int('lx41')
lx42 = z3.Int('lx42')

# List of components. phi-lib
phi1 = (Y1 == X11 ^ X12)
phi2 = (Y2 == -z3.If(z3.UGT(X21, X22), z3.BitVecVal(0, 8), z3.BitVecVal(1, 8)))
phi3 = (Y3 == X31 & X32)
phi4 = (Y4 == X41 ^ X42)

# Write the spec
spec = z3.And(z3.Implies(z3.UGE(J, I), O == J),
              z3.Implies(z3.UGT(I, J), O == I))

# phi cons = line number of two different instructions cannot be the same
phicons = z3.And(ly1 != ly2, ly2 != ly3, ly1 != ly3, ly1 != ly4, ly4 != ly2,
                 ly4 != ly3)

# We only have three instructions.
# Bound the line number of each instruction and operand.
phibound = z3.And(ly1 >= 1, ly1 <= 4, ly2 >= 1, ly2 <= 4, ly3 >= 1, ly3 <= 4,
                  ly4 >= 1, ly4 <= 4, lx11 >= -1, lx11 <= 4, lx12 >= -1,
                  lx12 <= 4, lx21 >= -1, lx21 <= 4, lx22 >= -1, lx22 <= 4,
                  lx31 >= -1, lx31 <= 4, lx32 >= -1, lx32 <= 4, lx41 >= -1,
                  lx41 <= 4, lx42 >= -1, lx42 <= 4)

# The operands of an instruction should use variables from previous lines. acyclicity