def test_struct_of_ints(self): ctx = newctx() point = it.StructType('Point', [it.IntType(64), it.IntType(64)]) q = dt.fresh_ptr(ctx, util.fresh_name('q'), it.PointerType(point)) print ctx['references'][q._ref._name] x = util.FreshBitVec('x', 64) q.getelementptr(ctx, util.i64(0), util.i64(0)).write(ctx, x) s = z3.Solver() s.add(z3.Not(x == q.getelementptr(ctx, util.i64(0), util.i64(0)).read(ctx))) self.assertEquals(s.check(), z3.unsat)
def test_pointer_pointer(self): ctx = newctx() p1 = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.PointerType(it.IntType(64)))) p2 = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.IntType(64))) p1.write(ctx, p2) p2.write(ctx, util.i64(10)) self.assertEquals(p2.read(ctx).as_long(), p1.read(ctx).read(ctx).as_long())
def test_pointer_pointer_pointer(self): ctx = newctx() a = dt.fresh_ptr(ctx, util.fresh_name( 'a'), it.PointerType(it.PointerType(it.IntType(64)))) b = dt.fresh_ptr(ctx, util.fresh_name( 'b'), it.PointerType(it.IntType(64))) c = dt.fresh_ptr(ctx, util.fresh_name( 'c'), it.PointerType(it.IntType(64))) cond = z3.Bool('cond') p = util.If(cond, b, c) a.write(ctx, p) print a.read(ctx).read(ctx)
def test_array_of_stucts(self): ctx = newctx() points = it.ArrayType(10, it.StructType( 'Point', [it.IntType(64), it.IntType(64)])) p = dt.fresh_ptr(ctx, util.fresh_name('p'), points) y = util.FreshBitVec('y', 64) x = util.FreshBitVec('x', 64) # x and y are within bounds ctx['solver'].add(z3.ULT(x, 10)) ctx['solver'].add(z3.ULT(y, 10)) p.getelementptr(ctx, x, util.i64(0)).write(ctx, x) s = z3.Solver() s.add(z3.Not(z3.Implies(x == y, p.getelementptr( ctx, y, util.i64(0)).read(ctx) == y))) self.assertEquals(s.check(), z3.unsat)
def test_read_read_same(self): # "Helgi's problem" ctx = newctx() p = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.IntType(64))) self.assertEquals(p.getelementptr(ctx, util.i64(0)).read( ctx), p.getelementptr(ctx, util.i64(0)).read(ctx))
def test_pointer_to_int(self): ctx = newctx() p = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.IntType(64))) print ctx['references'][p._ref._name] p.write(ctx, util.i64(4)) self.assertEquals(4, p.read(ctx).as_long())
def test_pointer_ite(self): ctx = newctx() p1 = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.IntType(64))) p2 = dt.fresh_ptr(ctx, util.fresh_name( 'p'), it.PointerType(it.IntType(64))) cond = z3.Bool('cond') p3 = util.If(cond, p1, p2) p3.write(ctx, util.i64(4)) s = z3.Solver() s.add(z3.Not(z3.Implies(cond, p1.read(ctx) == util.i64(4)))) self.assertEquals(s.check(), z3.unsat) s = z3.Solver() s.add(z3.Not(z3.Implies(z3.Not(cond), p2.read(ctx) == util.i64(4)))) self.assertEquals(s.check(), z3.unsat)
def test_array_bounds(self): ctx = newctx() points = it.ArrayType(10, it.IntType(64)) p = dt.fresh_ptr(ctx, util.fresh_name('p'), points) p = p.getelementptr(ctx, 50) with self.assertRaises(IndexError): p.write(ctx, util.i64(10))
def switch(self, ctx, value, value_type, default_case, *cases): if not cases: return default_case() case_value, case_value_type, case_branch = cases[0] cases = cases[1:] assert value_type == case_value_type def rest(): return self.switch(ctx, value, value_type, default_case, *cases) return self.branch(ctx, value == case_value, itypes.IntType(1), case_branch, rest)
def test_type_parsing(self): ctx = {} ctx['types'] = {} it.declare_struct_type(ctx, 'struct.trap_regs', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', 'i64', '[8 x i8]',) it.declare_struct_type(ctx, 'struct.proc', 'i32', 'i64', 'i64', '[16 x i64]', 'i64', '%struct.trap_regs = type { i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, [8 x i8] }', 'i64', '[8 x i8]',) self.assertEquals(it.parse_type(ctx, 'i64***'), it.PointerType(it.PointerType(it.PointerType(it.IntType(64))))) it.parse_type(ctx, 'i64***') it.parse_type(ctx, '[0 x i8]') it.parse_type(ctx, '[0 x i8]*') it.parse_type(ctx, '[3 x [4 x i32]]') it.parse_type(ctx, '[3 x [4 x i32]]') it.parse_type(ctx, '[3 x [4 x i32]]') it.parse_type(ctx, '%mytype = type { %struct.trap_regs*, i32 }')
# Patch z3 objects with some useful methods def _is_poison(self): """A z3 term is poison if it's name starts with poison, or any of its subterms are poison.""" if self.children(): for c in self.children(): if c.is_poison(): return True return False else: return self.sexpr().startswith('poison.') setattr(z3.BitVecRef, "type", lambda self: itypes.IntType(self.size())) setattr(z3.BoolRef, "type", lambda self: itypes.IntType(1)) setattr(z3.BoolRef, "size", lambda self: 1) setattr(z3.BitVecRef, "is_poison", _is_poison) setattr(z3.BoolRef, "is_poison", _is_poison) # Add copy support. Since z3 objects are immutable, copy / deepcopy can just # return the original object. setattr(z3.BitVecRef, '__copy__', lambda self: self) setattr(z3.BitVecRef, '__deepcopy__', lambda self, memo: self) setattr(z3.BoolRef, '__copy__', lambda self: self) setattr(z3.BoolRef, '__deepcopy__', lambda self, memo: self) setattr(z3.FuncDeclRef, '__copy__', lambda self: self) setattr(z3.FuncDeclRef, '__deepcopy__', lambda self, memo: self)