Skip to content

Commit

Permalink
Fix skipdata setup (capstone-engine#1320)
Browse files Browse the repository at this point in the history
* 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 capstone-engine#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
  • Loading branch information
MarSoft authored and aquynh committed Dec 31, 2018
1 parent 8f4cc4e commit 6c54814
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
31 changes: 28 additions & 3 deletions bindings/python/capstone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -897,21 +898,45 @@ def skipdata(self, opt):

@property
def skipdata_setup(self):
return
return (self._skipdata_mnem,) + self._skipdata_cb


@skipdata_setup.setter
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
Expand Down
18 changes: 13 additions & 5 deletions bindings/python/test_skipdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 6c54814

Please sign in to comment.