1
0
mirror of https://github.com/angr/pyvex synced 2026-06-21 13:47:01 +00:00
Files
pre-commit-ci[bot] add7ccfdf7 [pre-commit.ci] pre-commit autoupdate (#407)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.5.1 → v0.5.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.1...v0.5.2)

* Fix ruff errors

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Kevin Phoenix <kevin@kphoenix.us>
2024-07-15 12:59:16 -07:00

524 lines
16 KiB
Python

import copy
import gc
import logging
import os
import random
import sys
import unittest
import pyvex
from pyvex.lifting import LibVEXLifter
if sys.platform == "linux":
import resource
# pylint: disable=R0201
class TestPyvex(unittest.TestCase):
@unittest.skipUnless(
sys.platform == "linux", "Cannot import the resource package on windows, values different on macos."
)
def test_memory(self):
arches = [pyvex.ARCH_X86, pyvex.ARCH_PPC32, pyvex.ARCH_AMD64, pyvex.ARCH_ARM_BE]
# we're not including ArchMIPS32 cause it segfaults sometimes
# disable logging, as that may fill up log buffers somewhere
logging.disable(logging.ERROR)
for _ in range(10000):
try:
s = os.urandom(32)
a = random.choice(arches)
p = pyvex.IRSB(data=s, mem_addr=0, arch=a)
except pyvex.PyVEXError:
pass
kb_start = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
for _ in range(20000):
try:
s = os.urandom(32)
a = random.choice(arches)
p = pyvex.IRSB(data=s, mem_addr=0, arch=a)
except pyvex.PyVEXError:
pass
del p
gc.collect()
logging.disable(logging.NOTSET)
kb_end = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
pyvex.pvc.clear_log()
pyvex.pvc.LibVEX_ShowAllocStats()
print(LibVEXLifter.get_vex_log())
# allow a 5mb leeway
assert kb_end - kb_start < 5000
################
### IRCallee ###
################
def test_ircallee(self):
callee = pyvex.IRCallee(3, "test_name", 0xFFFFFF)
assert callee.name == "test_name"
assert callee.regparms == 3
assert callee.mcx_mask == 0xFFFFFF
############
### IRSB ###
############
def test_irsb_empty(self):
self.assertRaises(Exception, pyvex.IRSB)
self.assertRaises(Exception, pyvex.IRSB, data="", arch=pyvex.ARCH_AMD64, mem_addr=0)
def test_irsb_arm(self):
irsb = pyvex.IRSB(data=b"\x33\xff\x2f\xe1", mem_addr=0, arch=pyvex.ARCH_ARM_BE)
assert len([i for i in irsb.statements if isinstance(i, pyvex.IRStmt.IMark)]) == 1
def test_irsb_popret(self):
irsb = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
stmts = irsb.statements
irsb.pp()
assert len(stmts) > 0
assert irsb.jumpkind == "Ijk_Ret"
assert irsb.offsIP == 184
cursize = len(irsb.tyenv.types)
assert cursize > 0
print(irsb.statements[10].data)
print(irsb.statements[10].data.tmp)
print(irsb.tyenv.types[irsb.statements[10].data.tmp])
assert irsb.tyenv.lookup(irsb.statements[10].data.tmp) == "Ity_I64"
def test_two_irsb(self):
irsb1 = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
irsb2 = pyvex.IRSB(data=b"\x5d\x5d\x5d\x5d", mem_addr=0, arch=pyvex.ARCH_AMD64)
stmts1 = irsb1.statements
stmts2 = irsb2.statements
assert len(stmts1) != len(stmts2)
def test_irsb_deepCopy(self):
irsb = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
stmts = irsb.statements
irsb2 = copy.deepcopy(irsb)
stmts2 = irsb2.statements
assert len(stmts) == len(stmts2)
def test_irsb_addStmt(self):
irsb = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
stmts = irsb.statements
irsb2 = copy.deepcopy(irsb)
irsb2.statements = []
assert len(irsb2.statements) == 0
for n, i in enumerate(stmts):
assert len(irsb2.statements) == n
irsb2.statements.append(copy.deepcopy(i))
irsb2.pp()
def test_irsb_tyenv(self):
irsb = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
print(irsb.tyenv)
print("Orig")
print(irsb.tyenv)
print("Empty")
irsb2 = pyvex.IRSB.empty_block(arch=pyvex.ARCH_AMD64, addr=0)
print(irsb2.tyenv)
print("Unwrapped")
irsb2.tyenv = copy.deepcopy(irsb.tyenv)
print(irsb2.tyenv)
##################
### Statements ###
##################
def test_irstmt_pp(self):
irsb = pyvex.IRSB(data=b"\x5d\xc3", mem_addr=0, arch=pyvex.ARCH_AMD64)
stmts = irsb.statements
for i in stmts:
print("STMT: ", end=" ")
print(i)
def test_irstmt_flat(self):
print("TODO")
def test_irstmt_imark(self):
m = pyvex.IRStmt.IMark(1, 2, 3)
assert m.tag == "Ist_IMark"
assert m.addr == 1
assert m.len == 2
assert m.delta == 3
m.addr = 5
assert m.addr == 5
m.len = 5
assert m.len == 5
m.delta = 5
assert m.delta == 5
self.assertRaises(Exception, pyvex.IRStmt.IMark, ())
def test_irstmt_abihint(self):
self.assertRaises(Exception, pyvex.IRStmt.AbiHint, ())
a = pyvex.IRExpr.RdTmp.get_instance(123)
b = pyvex.IRExpr.RdTmp.get_instance(456)
m = pyvex.IRStmt.AbiHint(a, 10, b)
assert m.base.tmp == 123
assert m.len == 10
assert m.nia.tmp == 456
def test_irstmt_put(self):
self.assertRaises(Exception, pyvex.IRStmt.Put, ())
a = pyvex.IRExpr.RdTmp.get_instance(123)
m = pyvex.IRStmt.Put(a, 10)
print("Put stmt:", end=" ")
print(m)
print("")
assert m.data.tmp == 123
assert m.offset == 10
def test_irexpr_puti(self):
r = pyvex.IRRegArray(10, "Ity_I64", 20)
i = pyvex.IRExpr.RdTmp.get_instance(5)
d = pyvex.IRExpr.RdTmp.get_instance(30)
m = pyvex.IRStmt.PutI(r, i, d, 2)
assert m.descr.base == 10
assert m.ix.tmp == 5
assert m.bias == 2
assert m.data.tmp == d.tmp
self.assertRaises(Exception, pyvex.IRStmt.PutI, ())
def test_irstmt_wrtmp(self):
self.assertRaises(Exception, pyvex.IRStmt.WrTmp, ())
a = pyvex.IRExpr.RdTmp.get_instance(123)
m = pyvex.IRStmt.WrTmp(10, a)
assert m.tag == "Ist_WrTmp"
assert m.tmp == 10
assert m.data.tmp == 123
def test_irstmt_store(self):
self.assertRaises(Exception, pyvex.IRStmt.Store, ())
a = pyvex.IRExpr.RdTmp.get_instance(123)
d = pyvex.IRExpr.RdTmp.get_instance(456)
m = pyvex.IRStmt.Store(a, d, "Iend_LE")
assert m.tag == "Ist_Store"
assert m.endness == "Iend_LE"
assert m.addr.tmp == a.tmp
assert m.data.tmp == d.tmp
def test_irstmt_cas(self):
self.assertRaises(Exception, pyvex.IRStmt.CAS, ())
a = pyvex.IRExpr.RdTmp.get_instance(10)
eh = pyvex.IRExpr.RdTmp.get_instance(11)
el = pyvex.IRExpr.RdTmp.get_instance(12)
dh = pyvex.IRExpr.RdTmp.get_instance(21)
dl = pyvex.IRExpr.RdTmp.get_instance(22)
args = {
"oldHi": 1,
"oldLo": 2,
"end": "Iend_LE",
"addr": a,
"expdHi": eh,
"expdLo": el,
"dataHi": dh,
"dataLo": dl,
}
m = pyvex.IRStmt.CAS(**args)
assert m.tag == "Ist_CAS"
assert m.endness == "Iend_LE"
assert m.oldHi == 1
assert m.oldLo == 2
assert m.addr.tmp == a.tmp
assert m.expdHi.tmp == eh.tmp
assert m.expdLo.tmp == el.tmp
assert m.dataHi.tmp == dh.tmp
assert m.dataLo.tmp == dl.tmp
def test_irstmt_loadg(self):
self.assertRaises(Exception, pyvex.IRStmt.LoadG, ())
a = pyvex.IRExpr.RdTmp.get_instance(10)
alt = pyvex.IRExpr.RdTmp.get_instance(11)
guard = pyvex.IRExpr.RdTmp.get_instance(12)
args = {
"dst": 1,
"end": "Iend_LE",
"addr": a,
"alt": alt,
"guard": guard,
"cvt": "ILGop_Ident32",
}
m = pyvex.IRStmt.LoadG(**args)
assert m.tag == "Ist_LoadG"
assert m.end == "Iend_LE"
assert m.cvt == "ILGop_Ident32"
assert m.dst == 1
assert m.addr.tmp == a.tmp
assert m.alt.tmp == alt.tmp
assert m.guard.tmp == guard.tmp
assert m.cvt_types == ("Ity_I32", "Ity_I32")
def test_irstmt_storeg(self):
self.assertRaises(Exception, pyvex.IRStmt.LoadG, ())
a = pyvex.IRExpr.RdTmp.get_instance(10)
data = pyvex.IRExpr.RdTmp.get_instance(11)
guard = pyvex.IRExpr.RdTmp.get_instance(12)
args = {"end": "Iend_LE", "addr": a, "data": data, "guard": guard}
m = pyvex.IRStmt.StoreG(**args)
assert m.tag == "Ist_StoreG"
assert m.end == "Iend_LE"
assert m.addr.tmp == a.tmp
assert m.data.tmp == data.tmp
assert m.guard.tmp == guard.tmp
def test_irstmt_llsc(self):
self.assertRaises(Exception, pyvex.IRStmt.LLSC)
a = pyvex.IRExpr.RdTmp.get_instance(123)
d = pyvex.IRExpr.RdTmp.get_instance(456)
m = pyvex.IRStmt.LLSC(a, d, 1, "Iend_LE")
assert m.tag == "Ist_LLSC"
assert m.endness == "Iend_LE"
assert m.result == 1
assert m.addr.tmp == a.tmp
assert m.storedata.tmp == d.tmp
def test_irstmt_mbe(self):
m = pyvex.IRStmt.MBE("Imbe_CancelReservation")
assert m.event == "Imbe_CancelReservation"
m.event = "Imbe_Fence"
assert m.event == "Imbe_Fence"
def test_irstmt_dirty(self):
args = [pyvex.IRExpr.RdTmp.get_instance(i) for i in range(10)]
m = pyvex.IRStmt.Dirty("test_dirty", pyvex.IRConst.U8(1), args, 15, "Ifx_None", 0, 1, 0)
assert m.cee == "test_dirty"
assert isinstance(m.guard, pyvex.IRConst.U8)
assert m.tmp == 15
assert m.mFx == "Ifx_None"
assert m.nFxState == 0
for n, a in enumerate(m.args):
assert a.tmp == args[n].tmp
def test_irstmt_exit(self):
self.assertRaises(Exception, pyvex.IRStmt.Exit)
g = pyvex.IRExpr.RdTmp.get_instance(123)
d = pyvex.IRConst.U32(456)
m = pyvex.IRStmt.Exit(g, d, "Ijk_Ret", 10)
assert m.tag == "Ist_Exit"
assert m.jumpkind == "Ijk_Ret"
assert m.offsIP == 10
assert m.guard.tmp == g.tmp
assert m.dst.value == d.value
##################
### IRRegArray ###
##################
def test_irregarray(self):
m = pyvex.IRRegArray(10, "Ity_I64", 20)
assert m.nElems == 20
assert m.elemTy == "Ity_I64"
assert m.base == 10
################
### IRConst.s ###
################
def helper_const_subtype(self, subtype, tag, value):
print("Testing %s" % tag)
self.assertRaises(Exception, subtype)
c = subtype(value)
assert c.tag == tag
assert c.value == value
d = subtype(value - 1)
e = subtype(value)
assert c.value == e.value
assert e.value == c.value
self.assertNotEqual(c.value, d.value)
self.assertNotEqual(d.value, c.value)
self.assertNotEqual(c.value, "test")
# TODO: actually check value
assert c.type == d.type
def test_irconst(self):
self.helper_const_subtype(pyvex.IRConst.U1, "Ico_U1", 1)
self.helper_const_subtype(pyvex.IRConst.U8, "Ico_U8", 233)
self.helper_const_subtype(pyvex.IRConst.U16, "Ico_U16", 39852)
self.helper_const_subtype(pyvex.IRConst.U32, "Ico_U32", 3442312356)
self.helper_const_subtype(pyvex.IRConst.U64, "Ico_U64", 823452334523623455)
self.helper_const_subtype(pyvex.IRConst.F32, "Ico_F32", 13453.234375)
self.helper_const_subtype(pyvex.IRConst.F32i, "Ico_F32i", 3442312356)
self.helper_const_subtype(pyvex.IRConst.F64, "Ico_F64", 13453.234525)
self.helper_const_subtype(pyvex.IRConst.F64i, "Ico_F64i", 823457234523623455)
self.helper_const_subtype(pyvex.IRConst.V128, "Ico_V128", 39852)
self.helper_const_subtype(pyvex.IRConst.V256, "Ico_V256", 3442312356)
###################
### Expressions ###
###################
def test_irexpr_binder(self):
# binder doesn't work statically, but hopefully we should
# never see it, anyways
return
# m = pyvex.IRExpr.Binder(1534252)
# assert m.binder == 1534252
def test_irexpr_geti(self):
r = pyvex.IRRegArray(10, "Ity_I64", 20)
i = pyvex.IRExpr.RdTmp.get_instance(5)
m = pyvex.IRExpr.GetI(r, i, 2)
assert m.description.base == 10
assert m.index.tmp == 5
assert m.bias == 2
self.assertRaises(Exception, pyvex.IRExpr.GetI)
def test_irexpr_rdtmp(self):
m = pyvex.IRExpr.RdTmp.get_instance(123)
assert m.tag == "Iex_RdTmp"
assert m.tmp == 123
irsb = pyvex.IRSB(b"\x90\x5d\xc3", mem_addr=0x0, arch=pyvex.ARCH_AMD64)
print("TMP:", irsb.next.tmp)
def test_irexpr_get(self):
m = pyvex.IRExpr.Get(0, "Ity_I64")
assert m.type == "Ity_I64"
self.assertRaises(Exception, pyvex.IRExpr.Get)
def test_irexpr_qop(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
b = pyvex.IRExpr.Get(184, "Ity_I64")
c = pyvex.IRExpr.RdTmp.get_instance(1)
d = pyvex.IRExpr.RdTmp.get_instance(2)
op = "Iop_QAdd32S"
m = pyvex.IRExpr.Qop(op, [a, b, c, d])
assert m.op == op
assert m.args[1].type == b.type
assert len(m.args) == 4
assert m.args[2].tmp == c.tmp
def test_irexpr_triop(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
b = pyvex.IRExpr.Get(184, "Ity_I64")
c = pyvex.IRExpr.RdTmp.get_instance(1)
op = "Iop_MAddF64"
m = pyvex.IRExpr.Triop(op, [a, b, c])
assert m.op == op
assert m.args[1].type == b.type
assert len(m.args) == 3
assert m.args[2].tmp == c.tmp
def test_irexpr_binop(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
c = pyvex.IRExpr.RdTmp.get_instance(1)
op = "Iop_Add64"
m = pyvex.IRExpr.Binop(op, [a, c])
assert m.op == op
assert m.args[1].tmp == c.tmp
assert len(m.args) == 2
assert m.args[1].tmp == c.tmp
def test_irexpr_unop(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
op = "Iop_Add64"
m = pyvex.IRExpr.Unop(op, [a])
assert m.op == op
assert len(m.args) == 1
assert m.args[0].offset == a.offset
def test_irexpr_load(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
e = "Iend_LE"
t = "Ity_I64"
m = pyvex.IRExpr.Load(e, t, a)
assert m.endness == e
assert m.type == t
def test_irexpr_const(self):
u1 = pyvex.IRConst.U1(1)
f64 = pyvex.IRConst.F64(1.123)
ue = pyvex.IRExpr.Const(u1)
_ = pyvex.IRExpr.Const(f64)
assert ue.con.value == u1.value
assert ue.con.value != f64.value
def test_irexpr_ite(self):
a = pyvex.IRExpr.Get(0, "Ity_I64")
iffalse = pyvex.IRExpr.RdTmp.get_instance(1)
iftrue = pyvex.IRExpr.Const(pyvex.IRConst.U8(200))
m = pyvex.IRExpr.ITE(a, iffalse, iftrue)
assert m.iftrue.con.value == iftrue.con.value
def test_irexpr_ccall(self):
callee = pyvex.IRCallee(3, "test_name", 0xFFFFFF)
args = [pyvex.IRExpr.RdTmp.get_instance(i) for i in range(10)]
m = pyvex.IRExpr.CCall("Ity_I64", callee, args)
assert len(m.args) == len(args)
assert m.ret_type == "Ity_I64"
for n, a in enumerate(m.args):
assert a.tmp == args[n].tmp
m = pyvex.IRExpr.CCall(callee, "Ity_I64", ())
assert len(m.args) == 0
if __name__ == "__main__":
unittest.main()