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)
Example #2
0
    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()))