From 6c54814d2507895d37da9c97f88cfe33398a358a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D0=BC=D1=91=D0=BD=20=D0=9C=D0=B0=D1=80=D1=8C?= =?UTF-8?q?=D1=8F=D1=81=D0=B8=D0=BD?= Date: Mon, 31 Dec 2018 10:42:44 +0300 Subject: [PATCH] Fix skipdata setup (#1320) * Fix skipdata_setup for when _cb is None ctypes prototype does not accept None value, so if we want to get a NULL function pointer then we should either call it with no arguments or pass zero as an argument. Fixes #1316 * Do store and return skipdata_setup data * Add convenience wrappers for skipdata_setup * Uncomment skipdata_setup tests * Add alternate usage variants to test_skipdata.py * document getter --- bindings/python/capstone/__init__.py | 31 +++++++++++++++++++++++++--- bindings/python/test_skipdata.py | 18 +++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py index 027bfa1172..11c9acdba3 100644 --- a/bindings/python/capstone/__init__.py +++ b/bindings/python/capstone/__init__.py @@ -828,6 +828,7 @@ def __init__(self, arch, mode): # default mnemonic for SKIPDATA self._skipdata_mnem = ".byte" + self._skipdata_cb = (None, None) self._skipdata = False @@ -897,7 +898,7 @@ def skipdata(self, opt): @property def skipdata_setup(self): - return + return (self._skipdata_mnem,) + self._skipdata_cb @skipdata_setup.setter @@ -905,13 +906,37 @@ def skipdata_setup(self, opt): _skipdata_opt = _cs_opt_skipdata() _mnem, _cb, _ud = opt _skipdata_opt.mnemonic = _mnem.encode() - _skipdata_opt.callback = CS_SKIPDATA_CALLBACK(_cb) + _skipdata_opt.callback = CS_SKIPDATA_CALLBACK(_cb or 0) _skipdata_opt.user_data = ctypes.cast(_ud, ctypes.c_void_p) status = _cs.cs_option(self.csh, CS_OPT_SKIPDATA_SETUP, ctypes.cast(ctypes.byref(_skipdata_opt), ctypes.c_void_p)) if status != CS_ERR_OK: raise CsError(status) - self._skipdata_opt = _skipdata_opt + self._skipdata_mnem = _mnem + self._skipdata_cb = (_cb, _ud) + + + @property + def skipdata_mnem(self): + return self._skipdata_mnem + + + @skipdata_mnem.setter + def skipdata_mnem(self, mnem): + self.skipdata_setup = (mnem,) + self._skipdata_cb + + + @property + def skipdata_cb(self): + return self._skipdata_cb + + + @skipdata_cb.setter + def skipdata_cb(self, val): + if not isinstance(val, tuple): + val = (val, None) + func, data = val + self.skipdata_setup = (self._skipdata_mnem, func, data) # customize instruction mnemonic diff --git a/bindings/python/test_skipdata.py b/bindings/python/test_skipdata.py index eae9c62b9a..4817f9a65a 100755 --- a/bindings/python/test_skipdata.py +++ b/bindings/python/test_skipdata.py @@ -39,13 +39,21 @@ def test_class(): md.skipdata = True - # Default "data" instruction's name is ".byte". To rename it to "db", just uncomment + # Default "data" instruction's name is ".byte". To rename it to "db", just use # the code below. - # md.skipdata_setup = ("db", None, None) + md.skipdata_setup = ("db", None, None) # NOTE: This example ignores SKIPDATA's callback (first None) & user_data (second None) - - # To customize the SKIPDATA callback, uncomment the line below. - # md.skipdata_setup = (".db", testcb, None) + # Can also use dedicated setter + md.skipdata_mnem = 'db' + + # To customize the SKIPDATA callback, use the line below. + md.skipdata_setup = (".db", testcb, None) + # Or use dedicated setter with custom parameter + md.skipdata_cb = (testcb, 42) + # Or provide just a function + md.skipdata_cb = testcb + # Note that reading this property will always return a tuple + assert md.skipdata_cb == (testcb, None), md.skipdata_cb for insn in md.disasm(code, 0x1000): #bytes = binascii.hexlify(insn.bytes)