def test_state_merge(): a = SimState(arch='AMD64', mode='symbolic') a.memory.store(1, a.se.BVV(42, 8)) b = a.copy() c = b.copy() a.memory.store(2, a.memory.load(1, 1)+1) b.memory.store(2, b.memory.load(1, 1)*2) c.memory.store(2, c.memory.load(1, 1)/2) # make sure the byte at 1 is right nose.tools.assert_equal(a.se.eval(a.memory.load(1, 1)), 42) nose.tools.assert_equal(b.se.eval(b.memory.load(1, 1)), 42) nose.tools.assert_equal(c.se.eval(c.memory.load(1, 1)), 42) # make sure the byte at 2 is right nose.tools.assert_equal(a.se.eval(a.memory.load(2, 1)), 43) nose.tools.assert_equal(b.se.eval(b.memory.load(2, 1)), 84) nose.tools.assert_equal(c.se.eval(c.memory.load(2, 1)), 21) # the byte at 2 should be unique for all before the merge nose.tools.assert_true(a.se.unique(a.memory.load(2, 1))) nose.tools.assert_true(b.se.unique(b.memory.load(2, 1))) nose.tools.assert_true(c.se.unique(c.memory.load(2, 1))) logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.DEBUG) m, merge_conditions, merging_occurred = a.merge(b, c) logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.WARNING) nose.tools.assert_true(merging_occurred) #nose.tools.assert_equals(sorted(m.se.eval_upto(merge_flag, 10)), [ 0,1,2 ]) assert len(merge_conditions) == 3 # the byte at 2 should now *not* be unique for a nose.tools.assert_false(m.se.unique(m.memory.load(2, 1))) nose.tools.assert_true(a.se.unique(a.memory.load(2, 1))) nose.tools.assert_true(b.se.unique(b.memory.load(2, 1))) nose.tools.assert_true(c.se.unique(c.memory.load(2, 1))) # the byte at 2 should have the three values nose.tools.assert_items_equal(m.se.eval_upto(m.memory.load(2, 1), 10), (43, 84, 21)) # we should be able to select them by adding constraints a_a = m.copy() a_a.add_constraints(merge_conditions[0]) nose.tools.assert_true(a_a.se.unique(a_a.memory.load(2, 1))) nose.tools.assert_equal(a_a.se.eval(a_a.memory.load(2, 1)), 43) a_b = m.copy() a_b.add_constraints(merge_conditions[1]) nose.tools.assert_true(a_b.se.unique(a_b.memory.load(2, 1))) nose.tools.assert_equal(a_b.se.eval(a_b.memory.load(2, 1)), 84) a_c = m.copy() a_c.add_constraints(merge_conditions[2]) nose.tools.assert_true(a_c.se.unique(a_c.memory.load(2, 1))) nose.tools.assert_equal(a_c.se.eval(a_c.memory.load(2, 1)), 21) # test different sets of plugins a = SimState(arch='AMD64', mode='symbolic') nose.tools.assert_true(a.has_plugin('memory')) nose.tools.assert_true(a.has_plugin('registers')) nose.tools.assert_false(a.has_plugin('libc')) b = a.copy() a.get_plugin('libc') nose.tools.assert_true(a.has_plugin('libc')) nose.tools.assert_false(b.has_plugin('libc')) c = a.copy().merge(b.copy())[0] d = b.copy().merge(a.copy())[0] nose.tools.assert_true(c.has_plugin('libc')) nose.tools.assert_true(d.has_plugin('libc')) # test merging posix with different open files a = SimState(arch='AMD64', mode='symbolic') b = a.copy() a.posix.get_file(3) nose.tools.assert_equal(len(a.posix.files), 4) nose.tools.assert_equal(len(b.posix.files), 3) c = a.copy().merge(b.copy())[0] d = b.copy().merge(a.copy())[0] nose.tools.assert_equal(len(c.posix.files), 4) nose.tools.assert_equal(len(d.posix.files), 4)
def test_state_merge(self): a = SimState(arch="AMD64", mode="symbolic") a.memory.store(1, a.solver.BVV(42, 8)) b = a.copy() c = b.copy() a.memory.store(2, a.memory.load(1, 1) + 1) b.memory.store(2, b.memory.load(1, 1) * 2) c.memory.store(2, c.memory.load(1, 1) / 2) # make sure the byte at 1 is right assert a.solver.eval(a.memory.load(1, 1)) == 42 assert b.solver.eval(b.memory.load(1, 1)) == 42 assert c.solver.eval(c.memory.load(1, 1)) == 42 # make sure the byte at 2 is right assert a.solver.eval(a.memory.load(2, 1)) == 43 assert b.solver.eval(b.memory.load(2, 1)) == 84 assert c.solver.eval(c.memory.load(2, 1)) == 21 # the byte at 2 should be unique for all before the merge assert a.solver.unique(a.memory.load(2, 1)) assert b.solver.unique(b.memory.load(2, 1)) assert c.solver.unique(c.memory.load(2, 1)) # logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.DEBUG) m, merge_conditions, merging_occurred = a.merge(b, c) # logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.WARNING) assert merging_occurred # assert sorted(m.solver.eval_upto(merge_flag, 10)) == [ 0,1,2 ] assert len(merge_conditions) == 3 # the byte at 2 should now *not* be unique for a assert not m.solver.unique(m.memory.load(2, 1)) assert a.solver.unique(a.memory.load(2, 1)) assert b.solver.unique(b.memory.load(2, 1)) assert c.solver.unique(c.memory.load(2, 1)) # the byte at 2 should have the three values self.assertSequenceEqual( sorted(m.solver.eval_upto(m.memory.load(2, 1), 10)), (21, 43, 84)) # we should be able to select them by adding constraints a_a = m.copy() a_a.add_constraints(merge_conditions[0]) assert a_a.solver.unique(a_a.memory.load(2, 1)) assert a_a.solver.eval(a_a.memory.load(2, 1)) == 43 a_b = m.copy() a_b.add_constraints(merge_conditions[1]) assert a_b.solver.unique(a_b.memory.load(2, 1)) assert a_b.solver.eval(a_b.memory.load(2, 1)) == 84 a_c = m.copy() a_c.add_constraints(merge_conditions[2]) assert a_c.solver.unique(a_c.memory.load(2, 1)) assert a_c.solver.eval(a_c.memory.load(2, 1)) == 21 # test different sets of plugins a = SimState(arch="AMD64", mode="symbolic") assert a.has_plugin("memory") assert a.has_plugin("registers") assert not a.has_plugin("libc") b = a.copy() a.get_plugin("libc") assert a.has_plugin("libc") assert not b.has_plugin("libc") c = a.copy().merge(b.copy())[0] d = b.copy().merge(a.copy())[0] assert c.has_plugin("libc") assert d.has_plugin("libc") # test merging posix with different open files (illegal!) a = SimState(arch="AMD64", mode="symbolic") b = a.copy() a.posix.open(b"/tmp/idk", 1) self.assertRaises(angr.errors.SimMergeError, lambda: a.copy().merge(b.copy()))