1import nose 2import archinfo 3from pyvex import IRSB, lift, ffi 4from pyvex.lifting.util import Instruction, GymratLifter, JumpKind 5from pyvex.errors import PyVEXError 6 7def test_partial_lift(): 8 """This tests that gymrat correctly handles the case where an 9 instruction is longer than the remaining input. 10 """ 11 class NOP(Instruction): 12 name = "nop" 13 bin_format = "0000111100001111" 14 15 def compute_result(self, *args): 16 pass 17 18 class NOPLifter(GymratLifter): 19 instrs = [NOP] 20 21 lifter = NOPLifter(archinfo.ArchAMD64(), 0) 22 # this should not throw an exception 23 block = lifter._lift("\x0F\x0Fa") 24 nose.tools.assert_equal(block.size, 2) 25 nose.tools.assert_equal(block.instructions, 1) 26 nose.tools.assert_equal(block.jumpkind, JumpKind.NoDecode) 27 28 29def test_skipstmts_toomanyexits(): 30 31 # https://github.com/angr/pyvex/issues/153 32 33 old_exit_limit = IRSB.MAX_EXITS 34 IRSB.MAX_EXITS = 32 35 36 bytes_ = bytes.fromhex("0DF1B00B2EAB94E8030008938BE803000DF1C0089AE8030083E80300019B0DF1F00A339AE669E26193E8030085E8030098E8030083E80300069B95E8030088E80300A26993E803004A92002363622362A361E362A36238AC029A069484E8030012AC0998299328932B9303C885E8030092E8030084E803009AE8030082E803002A460A9D26993E910B9941910D9942910C992A93409548AD439194E803008AE8030027983F9927913F909BE803000DF5887B269335938BE803000DF58C7B089903C98BE8030098E8030084E8030095E8030088E803004B993391329394E80300349337933693069C059B4C93049B4E9350ABCDF834C1CDF83CE185E8030094E803004B9683E8030015A94498C4F7E2EA") 37 arch = archinfo.arch_from_id("ARMEL") 38 # Lifting the first four bytes will not cause any problem. Statements should be skipped as expected 39 b = IRSB(bytes_[:34], 0xC6951, arch, opt_level=1, bytes_offset=5, skip_stmts=True) 40 nose.tools.assert_greater(len(b.exit_statements), 0) 41 nose.tools.assert_false(b.has_statements, None) 42 43 # Lifting the entire block will cause the number of exit statements go beyond the limit (currently 32). PyVEX will 44 # automatically relift this block without skipping the statements 45 b = IRSB(bytes_, 0xC6951, arch, opt_level=1, bytes_offset=5, skip_stmts=True) 46 nose.tools.assert_is_not(b.statements, None) 47 nose.tools.assert_greater(len(b.exit_statements), 32) 48 49 # Restore the setting 50 IRSB.MAX_EXITS = old_exit_limit 51 52def test_max_bytes(): 53 data = bytes.fromhex('909090909090c3') 54 arch = archinfo.ArchX86() 55 nose.tools.assert_equal(lift(data, 0x1000, arch, max_bytes=None).size, len(data)) 56 nose.tools.assert_equal(lift(data, 0x1000, arch, max_bytes=len(data) - 1).size, len(data) - 1) 57 nose.tools.assert_equal(lift(data, 0x1000, arch, max_bytes=len(data) + 1).size, len(data)) 58 59 data2 = ffi.from_buffer(data) 60 nose.tools.assert_raises(PyVEXError, lift, data2, 0x1000, arch) 61 nose.tools.assert_equal(lift(data2, 0x1000, arch, max_bytes=len(data)).size, len(data)) 62 nose.tools.assert_equal(lift(data2, 0x1000, arch, max_bytes=len(data) - 1).size, len(data) - 1) 63 64if __name__ == '__main__': 65 test_partial_lift() 66 test_skipstmts_toomanyexits() 67 test_max_bytes() 68