summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--Makefile50
-rw-r--r--python/__init__.py26
-rw-r--r--python/architecture.py35
-rw-r--r--python/basicblock.py5
-rw-r--r--python/binaryview.py34
-rw-r--r--python/callingconvention.py7
-rw-r--r--python/databuffer.py4
-rw-r--r--python/demangle.py4
-rw-r--r--python/downloadprovider.py4
-rw-r--r--python/fileaccessor.py3
-rw-r--r--python/filemetadata.py2
-rw-r--r--python/function.py25
-rw-r--r--python/functionrecognizer.py14
-rw-r--r--python/highlight.py2
-rw-r--r--python/interaction.py17
-rw-r--r--python/log.py14
-rw-r--r--python/lowlevelil.py4
-rw-r--r--python/mainthread.py2
-rw-r--r--python/mediumlevelil.py2
-rw-r--r--python/metadata.py6
-rw-r--r--python/platform.py76
-rw-r--r--python/plugin.py19
-rw-r--r--python/pluginmanager.py6
-rw-r--r--python/scriptingprovider.py46
-rw-r--r--python/setting.py8
-rw-r--r--python/transform.py15
-rw-r--r--python/types.py15
-rw-r--r--python/undoaction.py4
-rw-r--r--python/update.py12
-rwxr-xr-xscripts/install_api.py2
m---------suite/binaries0
-rwxr-xr-xsuite/generator.py107
-rw-r--r--suite/testcommon.py282
-rw-r--r--suite/unit.py309
35 files changed, 620 insertions, 555 deletions
diff --git a/.gitignore b/.gitignore
index fc71333a..eff64eb4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,17 @@ CTestTestfile.cmake
api-docs/source/python.rst
api-docs/source/index.rst
.coverage
+# Make
+generator
+libcrypto.so.1.0.2
+libcurl.so.4
+libssl.so.1.0.2
+plugins/
+python/examples/binaryninja/
+python/libcrypto.so.1.0.2
+python/libcurl.so.4
+python/libssl.so.1.0.2
+python/plugins/
+python/types/
+suite/binaryninja/
+types/
diff --git a/Makefile b/Makefile
index 852569a0..e1576dcf 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,8 @@ json.o: ./json/jsoncpp.cpp ./json/json.h ./json/json-forwards.h
install: generate $(TARGET).a
@echo "Installing binaryninja API.";
cp -r python/* $(INSTALLPATH)/python/binaryninja
- cp $(TARGETDIR)/$(TARGET).a $(INSTALLPATH)
+ cp $(TARGET).a $(INSTALLPATH)
+ @echo "Done.";
generator: python/generator.cpp $(TARGET).a
@echo "Building generator...";
@@ -65,43 +66,36 @@ python_test: environment python/_binaryninjacore.py python/enums.py
oracle: environment python/_binaryninjacore.py python/enums.py
python3 suite/generator.py
-environment: python/_binaryninjacore.py python/enums.py
- @echo "Copying libs to needed locations..."
- @cp $(INSTALLPATH)/libbinaryninjacore.so.1 .
- @cp $(INSTALLPATH)/libcurl.so.4 .
- @cp $(INSTALLPATH)/libcrypto.so.1.0.2 .
- @cp $(INSTALLPATH)/libssl.so.1.0.2 .
-
- @mkdir -p api/python/examples
- @cp python/examples/bin_info.py api/python/examples/
- @cp $(INSTALLPATH)/libbinaryninjacore.so.1 api/python/
- @cp $(INSTALLPATH)/libcurl.so.4 api/python/
- @cp $(INSTALLPATH)/libcrypto.so.1.0.2 api/python/
- @cp $(INSTALLPATH)/libssl.so.1.0.2 api/python/
+environment: environment_clean python/_binaryninjacore.py python/enums.py
+ @echo "Copying over libs..."
+ cp $(INSTALLPATH)/libbinaryninjacore.so.1 .
+ cp $(INSTALLPATH)/libbinaryninjacore.so.1 python/
@echo "Building 'binaryninja' Packages..."
- @mkdir -p suite/binaryninja/
- @cp -r python/* suite/binaryninja/
- @mkdir -p api/python/examples/binaryninja/
- @cp -r python/* api/python/examples/binaryninja/
+ mkdir -p suite/binaryninja/
+ cp -r python/* suite/binaryninja/
+ cp -r suite/binaryninja/ python/examples/
@echo "Copying Architectures Over..."
- @cp -r $(INSTALLPATH)/types/ .
- @cp -r $(INSTALLPATH)/plugins/ .
- @cp -r $(INSTALLPATH)/plugins/ api/python/
+ cp -r $(INSTALLPATH)/types/ .
+ cp -r $(INSTALLPATH)/plugins/ .
+ cp -r $(INSTALLPATH)/types/ python/
+ cp -r $(INSTALLPATH)/plugins/ python/
environment_clean:
@echo "Removing 'binaryninja' Packages..."
- @rm -r suite/binaryninja/
- @rm -r api/
- -@rm suite/*.pyc
-
+ rm -rf suite/binaryninja/
+ rm -rf python/examples/binaryninja/
+
@echo "Removing libs..."
- @rm lib*
+ rm -f libbinaryninjacore.so.1
+ rm -f python/libbinaryninjacore.so.1
@echo "Removing Architectures..."
- @rm -r types/
- @rm -r plugins/
+ rm -rf types/
+ rm -rf plugins/
+ rm -rf python/types/
+ rm -rf python/plugins/
clean:
@echo " Cleaning...";
diff --git a/python/__init__.py b/python/__init__.py
index 2f7cc5a0..e1288b0a 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -25,6 +25,32 @@ import sys
import ctypes
from time import gmtime
+
+# 2-3 compatibility
+try:
+ import builtins # __builtins__ for python2
+except ImportError:
+ pass
+def range(*args):
+ """ A Python2 and Python3 Compatible Range Generator """
+ try:
+ return xrange(*args)
+ except NameError:
+ return builtins.range(*args)
+
+
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ class metaclass(type):
+ def __new__(cls, name, this_bases, d):
+ return meta(name, bases, d)
+
+ @classmethod
+ def __prepare__(cls, name, this_bases):
+ return meta.__prepare__(name, bases)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+
+
# Binary Ninja components
import binaryninja._binaryninjacore as core
# __all__ = [
diff --git a/python/architecture.py b/python/architecture.py
index 521c750a..aee7c301 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -23,13 +23,12 @@ import traceback
import ctypes
import abc
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import (Endianness, ImplicitRegisterExtend, BranchType,
InstructionTextTokenType, LowLevelILFlagCondition, FlagRole)
import binaryninja
from binaryninja import log
-
from binaryninja import lowlevelil
from binaryninja import types
from binaryninja import databuffer
@@ -37,8 +36,9 @@ from binaryninja import platform
from binaryninja import callingconvention
# 2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+from binaryninja import range
+from binaryninja import with_metaclass
+
class _ArchitectureMetaClass(type):
@@ -624,7 +624,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_full_width_registers(self, ctxt, count):
try:
- regs = self._full_width_regs.values()
+ regs = list(self._full_width_regs.values())
count[0] = len(regs)
reg_buf = (ctypes.c_uint * len(regs))()
for i in range(0, len(regs)):
@@ -639,7 +639,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_registers(self, ctxt, count):
try:
- regs = self._regs_by_index.keys()
+ regs = list(self._regs_by_index.keys())
count[0] = len(regs)
reg_buf = (ctypes.c_uint * len(regs))()
for i in range(0, len(regs)):
@@ -654,7 +654,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_flags(self, ctxt, count):
try:
- flags = self._flags_by_index.keys()
+ flags = list(self._flags_by_index.keys())
count[0] = len(flags)
flag_buf = (ctypes.c_uint * len(flags))()
for i in range(0, len(flags)):
@@ -669,7 +669,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_flag_write_types(self, ctxt, count):
try:
- write_types = self._flag_write_types_by_index.keys()
+ write_types = list(self._flag_write_types_by_index.keys())
count[0] = len(write_types)
type_buf = (ctypes.c_uint * len(write_types))()
for i in range(0, len(write_types)):
@@ -684,7 +684,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_semantic_flag_classes(self, ctxt, count):
try:
- sem_classes = self._semantic_flag_classes_by_index.keys()
+ sem_classes = list(self._semantic_flag_classes_by_index.keys())
count[0] = len(sem_classes)
class_buf = (ctypes.c_uint * len(sem_classes))()
for i in range(0, len(sem_classes)):
@@ -699,7 +699,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_semantic_flag_groups(self, ctxt, count):
try:
- sem_groups = self._semantic_flag_groups_by_index.keys()
+ sem_groups = list(self._semantic_flag_groups_by_index.keys())
count[0] = len(sem_groups)
group_buf = (ctypes.c_uint * len(sem_groups))()
for i in range(0, len(sem_groups)):
@@ -938,7 +938,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_register_stacks(self, ctxt, count):
try:
- regs = self._reg_stacks_by_index.keys()
+ regs = list(self._reg_stacks_by_index.keys())
count[0] = len(regs)
reg_buf = (ctypes.c_uint * len(regs))()
for i in range(0, len(regs)):
@@ -989,7 +989,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)):
def _get_all_intrinsics(self, ctxt, count):
try:
- regs = self._intrinsics_by_index.keys()
+ regs = list(self._intrinsics_by_index.keys())
count[0] = len(regs)
reg_buf = (ctypes.c_uint * len(regs))()
for i in range(0, len(regs)):
@@ -2415,8 +2415,8 @@ class CoreArchitecture(Architecture):
:param str code: string representation of the instructions to be assembled
:param int addr: virtual address that the instructions will be loaded at
- :return: the bytes for the assembled instructions or error string
- :rtype: (a tuple of instructions and empty string) or (or None and error string)
+ :return: the bytes for the assembled instructions
+ :rtype: Python3 - a 'bytes' object; Python2 - a 'str'
:Example:
>>> arch.assemble("je 10")
@@ -2426,8 +2426,11 @@ class CoreArchitecture(Architecture):
result = databuffer.DataBuffer()
errors = ctypes.c_char_p()
if not core.BNAssemble(self.handle, code, addr, result.handle, errors):
- return None, errors.value
- return str(result), errors.value
+ raise ValueError("Could not assemble")
+ if isinstance(str(result), bytes):
+ return str(result)
+ else:
+ return bytes(result)
def is_never_branch_patch_available(self, data, addr):
"""
diff --git a/python/basicblock.py b/python/basicblock.py
index b1f95ba3..11d5a7f4 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -20,14 +20,15 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import highlight
from binaryninja import _binaryninjacore as core
from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
+
class BasicBlockEdge(object):
def __init__(self, branch_type, source, target, back_edge):
diff --git a/python/binaryview.py b/python/binaryview.py
index b1bc4822..d439f563 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -23,7 +23,7 @@ import traceback
import ctypes
import abc
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import (AnalysisState, SymbolType, InstructionTextTokenType,
Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics)
@@ -38,8 +38,8 @@ from binaryninja import lineardisassembly
from binaryninja import metadata
# 2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+from binaryninja import range
+from binaryninja import with_metaclass
class BinaryDataNotification(object):
@@ -98,17 +98,19 @@ class StringReference(object):
@property
def value(self):
- return self.view.read(self.start, self.length)
+ return self.view.read(self.start, self.length).decode("charmap")
def __repr__(self):
return "<%s: %#x, len %#x>" % (self.type, self.start, self.length)
+_pending_analysis_completion_events = {}
class AnalysisCompletionEvent(object):
"""
The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving
callbacks when analysis is complete. The callback runs once. A completion event must be added
- for each new analysis in order to be notified of each analysis completion.
+ for each new analysis in order to be notified of each analysis completion. The
+ AnalysisCompletionEvent class takes responcibility for keeping track of the object's lifetime.
:Example:
>>> def on_complete(self):
@@ -122,11 +124,19 @@ class AnalysisCompletionEvent(object):
self.callback = callback
self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify)
self.handle = core.BNAddAnalysisCompletionEvent(self.view.handle, None, self._cb)
+ global _pending_analysis_completion_events
+ _pending_analysis_completion_events[id(self)] = self
def __del__(self):
+ global _pending_analysis_completion_events
+ if id(self) in _pending_analysis_completion_events:
+ del _pending_analysis_completion_events[id(self)]
core.BNFreeAnalysisCompletionEvent(self.handle)
def _notify(self, ctxt):
+ global _pending_analysis_completion_events
+ if id(self) in _pending_analysis_completion_events:
+ del _pending_analysis_completion_events[id(self)]
try:
self.callback(self)
except:
@@ -142,6 +152,9 @@ class AnalysisCompletionEvent(object):
"""
self.callback = self._empty_callback
core.BNCancelAnalysisCompletionEvent(self.handle)
+ global _pending_analysis_completion_events
+ if id(self) in _pending_analysis_completion_events:
+ del _pending_analysis_completion_events[id(self)]
class ActiveAnalysisInfo(object):
@@ -1731,10 +1744,13 @@ class BinaryView(object):
"""
``read`` returns the data reads at most ``length`` bytes from virtual address ``addr``.
+ Note: Python2 returns a str, but Python3 returns a bytes object. str(DataBufferObject) will
+ still get you a str in either case.
+
:param int addr: virtual address to read from.
:param int length: number of bytes to read.
:return: at most ``length`` bytes from the virtual address ``addr``, empty string on error or no data.
- :rtype: str
+ :rtype: python2 - str; python3 - bytes
:Example:
>>> #Opening a x86_64 Mach-O binary
@@ -2784,7 +2800,9 @@ class BinaryView(object):
def add_analysis_completion_event(self, callback):
"""
``add_analysis_completion_event`` sets up a call back function to be called when analysis has been completed.
- This is helpful when using asynchronously analysis.
+ This is helpful when using ``update_analysis`` which does not wait for analysis completion before returning.
+
+ The callee of this function is not resposible for maintaining the lifetime of the returned AnalysisCompletionEvent object.
:param callable() callback: A function to be called with no parameters when analysis has completed.
:return: An initialized AnalysisCompletionEvent object.
@@ -3481,7 +3499,7 @@ class BinaryView(object):
def get_unique_section_names(self, name_list):
incoming_names = (ctypes.c_char_p * len(name_list))()
for i in range(0, len(name_list)):
- incoming_names[i] = name_list[i]
+ incoming_names[i] = name_list[i].encode('charmap')
outgoing_names = core.BNGetUniqueSectionNames(self.handle, incoming_names, len(name_list))
result = []
for i in range(0, len(name_list)):
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 1b0d068e..6b906184 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -21,18 +21,17 @@
import traceback
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
from binaryninja import log
from binaryninja.enums import VariableSourceType
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class CallingConvention(object):
- from binaryninja import types
name = None
caller_saved_regs = []
int_arg_regs = []
@@ -48,7 +47,7 @@ class CallingConvention(object):
_registered_calling_conventions = []
- def __init__(self, arch=None, name=None, handle=None, confidence=types.max_confidence):
+ def __init__(self, arch=None, name=None, handle=None, confidence=binaryninja.types.max_confidence):
if handle is None:
if arch is None or name is None:
raise ValueError("Must specify either handle or architecture and name")
diff --git a/python/databuffer.py b/python/databuffer.py
index 1b29a7eb..298d0002 100644
--- a/python/databuffer.py
+++ b/python/databuffer.py
@@ -20,7 +20,7 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
@@ -114,7 +114,7 @@ class DataBuffer(object):
def __str__(self):
buf = ctypes.create_string_buffer(len(self))
ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self))
- if type(buf.raw) is str:
+ if isinstance(buf.raw, str):
return buf.raw
else:
return buf.raw.decode("charmap")
diff --git a/python/demangle.py b/python/demangle.py
index 90a19761..466324bc 100644
--- a/python/demangle.py
+++ b/python/demangle.py
@@ -20,11 +20,11 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
def get_qualified_name(names):
diff --git a/python/downloadprovider.py b/python/downloadprovider.py
index d34ca358..c714cb98 100644
--- a/python/downloadprovider.py
+++ b/python/downloadprovider.py
@@ -28,6 +28,7 @@ import traceback
# Binary Ninja Components
import binaryninja._binaryninjacore as core
from binaryninja.setting import Setting
+from binaryninja import with_metaclass
from binaryninja import startup
from binaryninja import log
@@ -109,8 +110,7 @@ class _DownloadProviderMetaclass(type):
raise AttributeError("attribute '%s' is read only" % name)
-class DownloadProvider(object):
- __metaclass__ = _DownloadProviderMetaclass
+class DownloadProvider(with_metaclass(_DownloadProviderMetaclass, object)):
name = None
instance_class = None
_registered_providers = []
diff --git a/python/fileaccessor.py b/python/fileaccessor.py
index 3c7c5e45..c2539b39 100644
--- a/python/fileaccessor.py
+++ b/python/fileaccessor.py
@@ -21,11 +21,10 @@
import traceback
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
class FileAccessor(object):
-
def __init__(self):
self._cb = core.BNFileAccessor()
self._cb.context = 0
diff --git a/python/filemetadata.py b/python/filemetadata.py
index ee69dce8..cafe1d67 100644
--- a/python/filemetadata.py
+++ b/python/filemetadata.py
@@ -22,7 +22,7 @@ from __future__ import absolute_import
import traceback
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja Components
import binaryninja
from binaryninja import _binaryninjacore as core
from binaryninja import associateddatastore #required for _FileMetadataAssociatedDataStore
diff --git a/python/function.py b/python/function.py
index 6392d7f2..8407eece 100644
--- a/python/function.py
+++ b/python/function.py
@@ -23,20 +23,20 @@ import threading
import traceback
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
+from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore
+from binaryninja import highlight
+from binaryninja import log
+from binaryninja import types
from binaryninja.enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType,
HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend,
DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType,
FunctionAnalysisSkipOverride)
-from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore
-from binaryninja import types
-from binaryninja import highlight
-from binaryninja import log
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class LookupTableEntry(object):
@@ -49,7 +49,7 @@ class LookupTableEntry(object):
class RegisterValue(object):
- def __init__(self, arch = None, value = None, confidence = binaryninja.types.max_confidence):
+ def __init__(self, arch = None, value = None, confidence = types.max_confidence):
self.is_constant = False
if value is None:
self.type = RegisterValueType.UndeterminedValue
@@ -1160,6 +1160,8 @@ class Function(object):
for j in range(0, lines[i].count):
token_type = InstructionTextTokenType(lines[i].tokens[j].type)
text = lines[i].tokens[j].text
+ if not isinstance(text, str):
+ text = text.encode("charmap")
value = lines[i].tokens[j].value
size = lines[i].tokens[j].size
operand = lines[i].tokens[j].operand
@@ -1836,6 +1838,7 @@ class DisassemblySettings(object):
core.BNSetDisassemblySettingsOption(self.handle, option, state)
+_pending_function_graph_completion_events = {}
class FunctionGraph(object):
def __init__(self, view, handle):
self.view = view
@@ -1969,6 +1972,9 @@ class FunctionGraph(object):
try:
if self._on_complete is not None:
self._on_complete()
+ global _pending_function_graph_completion_events
+ if id(self) in _pending_function_graph_completion_events:
+ del _pending_function_graph_completion_events[id(self)]
except:
log.log_error(traceback.format_exc())
@@ -1993,11 +1999,16 @@ class FunctionGraph(object):
self._wait_cond.release()
def on_complete(self, callback):
+ global _pending_function_graph_completion_events
+ _pending_function_graph_completion_events[id(self)] = self
self._on_complete = callback
core.BNSetFunctionGraphCompleteCallback(self.handle, None, self._cb)
def abort(self):
core.BNAbortFunctionGraph(self.handle)
+ global _pending_function_graph_completion_events
+ if id(self) in _pending_function_graph_completion_events:
+ del _pending_function_graph_completion_events[id(self)]
def get_blocks_in_region(self, left, top, right, bottom):
count = ctypes.c_ulonglong()
diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py
index e390a3c8..319bff0e 100644
--- a/python/functionrecognizer.py
+++ b/python/functionrecognizer.py
@@ -20,15 +20,15 @@
import traceback
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
+from binaryninja import function
+from binaryninja import filemetadata
+from binaryninja import binaryview
+from binaryninja import lowlevelil
class FunctionRecognizer(object):
- from binaryninja import function
- from binaryninja import filemetadata
- from binaryninja import binaryview
- from binaryninja import lowlevelil
_instance = None
@@ -54,7 +54,7 @@ class FunctionRecognizer(object):
try:
file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data))
view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data))
- func = binaryninja.function.Function(view, handle = core.BNNewFunctionReference(func))
+ func = function.Function(view, handle = core.BNNewFunctionReference(func))
il = lowlevelil.LowLevelILFunction(func.arch, handle = core.BNNewLowLevelILFunctionReference(il))
return self.recognize_low_level_il(view, func, il)
except:
@@ -68,7 +68,7 @@ class FunctionRecognizer(object):
try:
file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data))
view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data))
- func = binaryninja.function.Function(view, handle = core.BNNewFunctionReference(func))
+ func = function.Function(view, handle = core.BNNewFunctionReference(func))
il = mediumlevelil.MediumLevelILFunction(func.arch, handle = core.BNNewMediumLevelILFunctionReference(il))
return self.recognize_medium_level_il(view, func, il)
except:
diff --git a/python/highlight.py b/python/highlight.py
index b04561bd..55246a9a 100644
--- a/python/highlight.py
+++ b/python/highlight.py
@@ -19,7 +19,7 @@
# IN THE SOFTWARE.
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import HighlightColorStyle, HighlightStandardColor
diff --git a/python/interaction.py b/python/interaction.py
index 5b78b278..49b4e024 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -21,12 +21,13 @@
import ctypes
import traceback
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult
+from binaryninja import binaryview
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class LabelField(object):
@@ -152,7 +153,11 @@ class AddressField(object):
class ChoiceField(object):
"""
``ChoiceField`` prompts the user to choose from the list of strings provided in ``choices``. Result is stored
- in self.result as an index in to the coices array.
+ in self.result as an index in to the choices array.
+
+ :attr str prompt: prompt to be presented to the user
+ :attr list(str) choices: list of choices to choose from
+
"""
def __init__(self, prompt, choices):
self.prompt = prompt
@@ -164,7 +169,7 @@ class ChoiceField(object):
value.prompt = self.prompt
choice_buf = (ctypes.c_char_p * len(self.choices))()
for i in range(0, len(self.choices)):
- choice_buf[i] = str(self.choices[i])
+ choice_buf[i] = self.choices[i].encode('charmap')
value.choices = choice_buf
value.count = len(self.choices)
@@ -242,8 +247,6 @@ class DirectoryNameField(object):
class InteractionHandler(object):
-
- from binaryninja import binaryview
_interaction_handler = None
def __init__(self):
@@ -617,7 +620,7 @@ def get_choice_input(prompt, title, choices):
"""
choice_buf = (ctypes.c_char_p * len(choices))()
for i in range(0, len(choices)):
- choice_buf[i] = str(choices[i])
+ choice_buf[i] = str(choices[i]).encode('charmap')
value = ctypes.c_ulonglong()
if not core.BNGetChoiceInput(value, prompt, title, choice_buf, len(choices)):
return None
diff --git a/python/log.py b/python/log.py
index d4d87019..9a5e1358 100644
--- a/python/log.py
+++ b/python/log.py
@@ -19,7 +19,7 @@
# IN THE SOFTWARE.
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import LogLevel
@@ -55,7 +55,7 @@ def log(level, text):
:param str text: message to print
:rtype: None
"""
- core.BNLog(level, "%s", str(text))
+ core.BNLog(level,text)
def log_debug(text):
@@ -70,7 +70,7 @@ def log_debug(text):
>>> log_debug("Hotdogs!")
Hotdogs!
"""
- core.BNLogDebug("%s", str(text))
+ core.BNLogDebug(text)
def log_info(text):
@@ -85,7 +85,7 @@ def log_info(text):
Saucisson!
>>>
"""
- core.BNLogInfo("%s", str(text))
+ core.BNLogInfo(text)
def log_warn(text):
@@ -101,7 +101,7 @@ def log_warn(text):
Chilidogs!
>>>
"""
- core.BNLogWarn("%s", str(text))
+ core.BNLogWarn(text)
def log_error(text):
@@ -117,7 +117,7 @@ def log_error(text):
Spanferkel!
>>>
"""
- core.BNLogError("%s", str(text))
+ core.BNLogError(text)
def log_alert(text):
@@ -133,7 +133,7 @@ def log_alert(text):
Kielbasa!
>>>
"""
- core.BNLogAlert("%s", str(text))
+ core.BNLogAlert(text)
def log_to_stdout(min_level=LogLevel.InfoLog):
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 272b2474..e714eb48 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -21,14 +21,14 @@
import ctypes
import struct
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType
from binaryninja import basicblock #required for LowLevelILBasicBlock
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class LowLevelILLabel(object):
diff --git a/python/mainthread.py b/python/mainthread.py
index 16938f1a..5b0cd53c 100644
--- a/python/mainthread.py
+++ b/python/mainthread.py
@@ -18,7 +18,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja import scriptingprovider
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index f7e9951a..cfa8f900 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -30,7 +30,7 @@ from binaryninja import types
from binaryninja import lowlevelil
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class SSAVariable(object):
diff --git a/python/metadata.py b/python/metadata.py
index fed8bdaa..b17bbf4f 100644
--- a/python/metadata.py
+++ b/python/metadata.py
@@ -22,12 +22,12 @@
from __future__ import absolute_import
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import MetadataType
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class Metadata(object):
@@ -147,7 +147,7 @@ class Metadata(object):
result = core.BNMetadataGetValueStore(self.handle)
try:
for i in range(result.contents.size):
- if type(result.contents.keys[i]) is bytes:
+ if isinstance(result.contents.keys[i], bytes):
yield str(result.contents.keys[i].decode('charmap'))
else:
yield result.contents.keys[i]
diff --git a/python/platform.py b/python/platform.py
index c57315ce..9a5f70df 100644
--- a/python/platform.py
+++ b/python/platform.py
@@ -20,18 +20,18 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
+from binaryninja import types
-#2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
+from binaryninja import with_metaclass
class _PlatformMetaClass(type):
- from binaryninja import types
@property
def list(self):
binaryninja._init_plugins()
@@ -240,8 +240,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
type_list = core.BNGetPlatformTypes(self.handle, count)
result = {}
for i in range(0, count.value):
- name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name)
- result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(type_list[i].name)
+ result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
core.BNFreeTypeList(type_list, count.value)
return result
@@ -252,8 +252,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
type_list = core.BNGetPlatformVariables(self.handle, count)
result = {}
for i in range(0, count.value):
- name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name)
- result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(type_list[i].name)
+ result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
core.BNFreeTypeList(type_list, count.value)
return result
@@ -264,8 +264,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
type_list = core.BNGetPlatformFunctions(self.handle, count)
result = {}
for i in range(0, count.value):
- name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name)
- result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(type_list[i].name)
+ result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self)
core.BNFreeTypeList(type_list, count.value)
return result
@@ -276,8 +276,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
call_list = core.BNGetPlatformSystemCalls(self.handle, count)
result = {}
for i in range(0, count.value):
- name = binaryninja.types.QualifiedName._from_core_struct(call_list[i].name)
- t = binaryninja.types.Type(core.BNNewTypeReference(call_list[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(call_list[i].name)
+ t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self)
result[call_list[i].number] = (name, t)
core.BNFreeSystemCallList(call_list, count.value)
return result
@@ -328,25 +328,25 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
return Platform(None, handle = result), new_addr.value
def get_type_by_name(self, name):
- name = binaryninja.types.QualifiedName(name)._get_core_struct()
+ name = types.QualifiedName(name)._get_core_struct()
obj = core.BNGetPlatformTypeByName(self.handle, name)
if not obj:
return None
- return binaryninja.types.Type(obj, platform = self)
+ return types.Type(obj, platform = self)
def get_variable_by_name(self, name):
- name = binaryninja.types.QualifiedName(name)._get_core_struct()
+ name = types.QualifiedName(name)._get_core_struct()
obj = core.BNGetPlatformVariableByName(self.handle, name)
if not obj:
return None
- return binaryninja.types.Type(obj, platform = self)
+ return types.Type(obj, platform = self)
def get_function_by_name(self, name):
- name = binaryninja.types.QualifiedName(name)._get_core_struct()
+ name = types.QualifiedName(name)._get_core_struct()
obj = core.BNGetPlatformFunctionByName(self.handle, name)
if not obj:
return None
- return binaryninja.types.Type(obj, platform = self)
+ return types.Type(obj, platform = self)
def get_system_call_name(self, number):
return core.BNGetPlatformSystemCallName(self.handle, number)
@@ -355,15 +355,15 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
obj = core.BNGetPlatformSystemCallType(self.handle, number)
if not obj:
return None
- return binaryninja.types.Type(obj, platform = self)
+ return types.Type(obj, platform = self)
def generate_auto_platform_type_id(self, name):
- name = binaryninja.types.QualifiedName(name)._get_core_struct()
+ name = types.QualifiedName(name)._get_core_struct()
return core.BNGenerateAutoPlatformTypeId(self.handle, name)
def generate_auto_platform_type_ref(self, type_class, name):
type_id = self.generate_auto_platform_type_id(name)
- return binaryninja.types.NamedTypeReference(type_class, type_id, name)
+ return types.NamedTypeReference(type_class, type_id, name)
def get_auto_platform_type_id_source(self):
return core.BNGetAutoPlatformTypeIdSource(self.handle)
@@ -391,7 +391,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
filename = "input"
dir_buf = (ctypes.c_char_p * len(include_dirs))()
for i in range(0, len(include_dirs)):
- dir_buf[i] = str(include_dirs[i])
+ dir_buf[i] = include_dirs[i].encode('charmap')
parse = core.BNTypeParserResult()
errors = ctypes.c_char_p()
result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf,
@@ -404,16 +404,16 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
variables = {}
functions = {}
for i in range(0, parse.typeCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name)
- type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.types[i].name)
+ type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self)
for i in range(0, parse.variableCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name)
- variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.variables[i].name)
+ variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self)
for i in range(0, parse.functionCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name)
- functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.functions[i].name)
+ functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self)
core.BNFreeTypeParserResult(parse)
- return binaryninja.types.TypeParserResult(type_dict, variables, functions)
+ return types.TypeParserResult(type_dict, variables, functions)
def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None):
"""
@@ -437,7 +437,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
"""
dir_buf = (ctypes.c_char_p * len(include_dirs))()
for i in range(0, len(include_dirs)):
- dir_buf[i] = str(include_dirs[i])
+ dir_buf[i] = include_dirs[i].encode('charmap')
parse = core.BNTypeParserResult()
errors = ctypes.c_char_p()
result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf,
@@ -450,13 +450,13 @@ class Platform(with_metaclass(_PlatformMetaClass, object)):
variables = {}
functions = {}
for i in range(0, parse.typeCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name)
- type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.types[i].name)
+ type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self)
for i in range(0, parse.variableCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name)
- variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.variables[i].name)
+ variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self)
for i in range(0, parse.functionCount):
- name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name)
- functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self)
+ name = types.QualifiedName._from_core_struct(parse.functions[i].name)
+ functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self)
core.BNFreeTypeParserResult(parse)
- return binaryninja.types.TypeParserResult(type_dict, variables, functions)
+ return types.TypeParserResult(type_dict, variables, functions)
diff --git a/python/plugin.py b/python/plugin.py
index 52feced4..b8217f0b 100644
--- a/python/plugin.py
+++ b/python/plugin.py
@@ -22,15 +22,18 @@ import traceback
import ctypes
import threading
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import log
from binaryninja import _binaryninjacore as core
from binaryninja.enums import PluginCommandType
+from binaryninja import filemetadata
+from binaryninja import binaryview
+from binaryninja import function
-#2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
+from binaryninja import with_metaclass
class PluginCommandContext(object):
@@ -43,7 +46,6 @@ class PluginCommandContext(object):
class _PluginCommandMetaClass(type):
-
@property
def list(self):
binaryninja._init_plugins()
@@ -73,11 +75,6 @@ class _PluginCommandMetaClass(type):
class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)):
-
- from binaryninja import filemetadata
- from binaryninja import binaryview
- from binaryninja import function
-
_registered_commands = []
def __init__(self, cmd):
@@ -540,7 +537,6 @@ class MainThreadAction(object):
class MainThreadActionHandler(object):
-
_main_thread = None
def __init__(self):
@@ -586,7 +582,6 @@ class _BackgroundTaskMetaclass(type):
class BackgroundTask(with_metaclass(_BackgroundTaskMetaclass, object)):
-
def __init__(self, initial_progress_text = "", can_cancel = False, handle = None):
if handle is None:
self.handle = core.BNBeginBackgroundTask(initial_progress_text, can_cancel)
diff --git a/python/pluginmanager.py b/python/pluginmanager.py
index ad314629..c7a0c83a 100644
--- a/python/pluginmanager.py
+++ b/python/pluginmanager.py
@@ -20,11 +20,12 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
+
class RepoPlugin(object):
"""
@@ -201,7 +202,6 @@ class RepositoryManager(object):
``RepositoryManager`` Keeps track of all the repositories and keeps the enabled_plugins.json file coherent with
the plugins that are installed/unstalled enabled/disabled
"""
-
def __init__(self, handle=None):
raise Exception("RepositoryManager temporarily disabled!")
self.handle = core.BNGetRepositoryManager()
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 374b2f41..37642ed4 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -26,14 +26,15 @@ import threading
import abc
import sys
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
+import binaryninja
from binaryninja import _binaryninjacore as core
from binaryninja.enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState
-import binaryninja.log
+from binaryninja import log
-#2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
+from binaryninja import with_metaclass
class _ThreadActionContext(object):
@@ -75,19 +76,19 @@ class ScriptingOutputListener(object):
try:
self.notify_output(text)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _error(self, ctxt, text):
try:
self.notify_error(text)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _input_ready_state_changed(self, ctxt, state):
try:
self.notify_input_ready_state_changed(state)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def notify_output(self, text):
pass
@@ -123,13 +124,13 @@ class ScriptingInstance(object):
try:
self.perform_destroy_instance()
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _execute_script_input(self, ctxt, text):
try:
return self.perform_execute_script_input(text)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
return ScriptingProviderExecuteResult.InvalidScriptInput
def _set_current_binary_view(self, ctxt, view):
@@ -140,7 +141,7 @@ class ScriptingInstance(object):
view = None
self.perform_set_current_binary_view(view)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _set_current_function(self, ctxt, func):
try:
@@ -150,7 +151,7 @@ class ScriptingInstance(object):
func = None
self.perform_set_current_function(func)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _set_current_basic_block(self, ctxt, block):
try:
@@ -165,19 +166,19 @@ class ScriptingInstance(object):
block = None
self.perform_set_current_basic_block(block)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _set_current_address(self, ctxt, addr):
try:
self.perform_set_current_address(addr)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
def _set_current_selection(self, ctxt, begin, end):
try:
self.perform_set_current_selection(begin, end)
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
@abc.abstractmethod
def perform_destroy_instance(self):
@@ -324,7 +325,7 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)):
return None
return ctypes.cast(core.BNNewScriptingInstanceReference(result.handle), ctypes.c_void_p).value
except:
- binaryninja.log.log_error(traceback.format_exc())
+ log.log_error(traceback.format_exc())
return None
def create_instance(self):
@@ -390,7 +391,7 @@ class _PythonScriptingInstanceOutput(object):
interpreter = PythonScriptingInstance._interpreter.value
if interpreter is None:
- if binaryninja.log.is_output_redirected_to_log():
+ if log.is_output_redirected_to_log():
self.buffer += data
while True:
i = self.buffer.find('\n')
@@ -400,9 +401,9 @@ class _PythonScriptingInstanceOutput(object):
self.buffer = self.buffer[i + 1:]
if self.is_error:
- binaryninja.log.log_error(line)
+ log.log_error(line)
else:
- binaryninja.log.log_info(line)
+ log.log_info(line)
else:
self.orig.write(data)
else:
@@ -490,7 +491,7 @@ class PythonScriptingInstance(ScriptingInstance):
self.code = None
self.input = ""
- self.interpreter.push("from binaryninja import *\n")
+ self.interpreter.push("from binaryninja import *")
def execute(self, code):
self.code = code
@@ -553,8 +554,8 @@ class PythonScriptingInstance(ScriptingInstance):
self.locals["current_llil"] = self.active_func.low_level_il
self.locals["current_mlil"] = self.active_func.medium_level_il
- for line in code.split("\n"):
- self.interpreter.push(line)
+ for line in code.split(b'\n'):
+ self.interpreter.push(line.decode('charmap'))
if self.locals["here"] != self.active_addr:
if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]):
@@ -660,3 +661,4 @@ def redirect_stdio():
sys.stdin = _PythonScriptingInstanceInput(sys.stdin)
sys.stdout = _PythonScriptingInstanceOutput(sys.stdout, False)
sys.stderr = _PythonScriptingInstanceOutput(sys.stderr, True)
+ sys.excepthook = sys.__excepthook__ \ No newline at end of file
diff --git a/python/setting.py b/python/setting.py
index fea06140..355492aa 100644
--- a/python/setting.py
+++ b/python/setting.py
@@ -20,11 +20,11 @@
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
# 2-3 compatibility
-from six.moves import range
+from binaryninja import range
class Setting(object):
@@ -113,7 +113,7 @@ class Setting(object):
length.value = len(value)
default_list = (ctypes.c_char_p * len(value))()
for i in range(len(value)):
- default_list[i] = value[i].encode('utf-8')
+ default_list[i] = value[i].encode('charmap')
return core.BNSettingSetStringList(self.plugin_name, name, default_list, length, auto_flush)
@@ -141,4 +141,4 @@ class Setting(object):
core.BNSettingRemoveSettingGroup(self.plugin_name, auto_flush)
def remove_setting(self, setting, auto_flush=True):
- core.BNSettingRemoveSetting(self.plugin_name, setting, auto_flush) \ No newline at end of file
+ core.BNSettingRemoveSetting(self.plugin_name, setting, auto_flush)
diff --git a/python/transform.py b/python/transform.py
index e16c6bfc..1734d248 100644
--- a/python/transform.py
+++ b/python/transform.py
@@ -22,20 +22,19 @@ import traceback
import ctypes
import abc
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import log
from binaryninja import databuffer
from binaryninja import _binaryninjacore as core
from binaryninja.enums import TransformType
-#2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
+from binaryninja import with_metaclass
class _TransformMetaClass(type):
-
@property
def list(self):
binaryninja._init_plugins()
@@ -96,8 +95,6 @@ class TransformParameter(object):
class Transform(with_metaclass(_TransformMetaClass, object)):
-
- from binaryninja import databuffer
transform_type = None
name = None
long_name = None
@@ -224,7 +221,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)):
def decode(self, input_buf, params = {}):
input_buf = databuffer.DataBuffer(input_buf)
output_buf = databuffer.DataBuffer()
- keys = params.keys()
+ keys = list(params.keys())
param_buf = (core.BNTransformParameter * len(keys))()
for i in range(0, len(keys)):
data = databuffer.DataBuffer(params[keys[i]])
@@ -237,7 +234,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)):
def encode(self, input_buf, params = {}):
input_buf = databuffer.DataBuffer(input_buf)
output_buf = databuffer.DataBuffer()
- keys = params.keys()
+ keys = list(params.keys())
param_buf = (core.BNTransformParameter * len(keys))()
for i in range(0, len(keys)):
data = databuffer.DataBuffer(params[keys[i]])
diff --git a/python/types.py b/python/types.py
index 2ad8d2c2..e8ce7464 100644
--- a/python/types.py
+++ b/python/types.py
@@ -23,23 +23,26 @@ max_confidence = 255
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
import binaryninja
from binaryninja import _binaryninjacore as core
from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType
-#2-3 compatibility
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
class QualifiedName(object):
def __init__(self, name = []):
if isinstance(name, str):
self.name = [name]
+ self.byte_name = [name.encode('charmap')]
elif isinstance(name, QualifiedName):
self.name = name.name
+ self.byte_name = [n.encode('charmap') for n in name.name]
else:
- self.name = [i.decode('utf-8') for i in name]
+ self.name = [i.decode('charmap') for i in name]
+ self.byte_name = name
def __str__(self):
return "::".join(self.name)
@@ -102,7 +105,7 @@ class QualifiedName(object):
result = core.BNQualifiedName()
name_list = (ctypes.c_char_p * len(self.name))()
for i in range(0, len(self.name)):
- name_list[i] = self.name[i]
+ name_list[i] = self.name[i].encode('charmap')
result.name = name_list
result.nameCount = len(self.name)
return result
@@ -1022,7 +1025,7 @@ def preprocess_source(source, filename=None, include_dirs=[]):
filename = "input"
dir_buf = (ctypes.c_char_p * len(include_dirs))()
for i in range(0, len(include_dirs)):
- dir_buf[i] = str(include_dirs[i])
+ dir_buf[i] = include_dirs[i].encode('charmap')
output = ctypes.c_char_p()
errors = ctypes.c_char_p()
result = core.BNPreprocessSource(source, filename, output, errors, dir_buf, len(include_dirs))
diff --git a/python/undoaction.py b/python/undoaction.py
index 732d559a..7891bf54 100644
--- a/python/undoaction.py
+++ b/python/undoaction.py
@@ -22,14 +22,12 @@ import traceback
import json
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import ActionType
class UndoAction(object):
-
-
name = None
action_type = None
_registered = False
diff --git a/python/update.py b/python/update.py
index 4c77b202..7f5d6f9c 100644
--- a/python/update.py
+++ b/python/update.py
@@ -21,18 +21,16 @@
import traceback
import ctypes
-# Binary Ninja components -- additional imports belong in the appropriate class
+# Binary Ninja components
from binaryninja import _binaryninjacore as core
from binaryninja.enums import UpdateResult
-
-#2-3 compatibility
-from six import with_metaclass
-from six.moves import range
+# 2-3 compatibility
+from binaryninja import range
+from binaryninja import with_metaclass
class _UpdateChannelMetaClass(type):
-
@property
def list(self):
binaryninja._init_plugins()
@@ -99,7 +97,6 @@ class _UpdateChannelMetaClass(type):
class UpdateProgressCallback(object):
-
def __init__(self, func):
self.cb = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(self.callback)
self.func = func
@@ -114,7 +111,6 @@ class UpdateProgressCallback(object):
class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)):
-
def __init__(self, name, desc, ver):
self.name = name
self.description = desc
diff --git a/scripts/install_api.py b/scripts/install_api.py
index 53679ba5..3cc0ed0d 100755
--- a/scripts/install_api.py
+++ b/scripts/install_api.py
@@ -80,6 +80,6 @@ else:
sys.exit(1)
binaryninja_pth_path = os.path.join(install_path, 'binaryninja.pth')
-open(binaryninja_pth_path, 'wb').write(api_path)
+open(binaryninja_pth_path, 'wb').write(api_path.encode('charmap'))
print("Binary Ninja API installed using {}".format(binaryninja_pth_path))
diff --git a/suite/binaries b/suite/binaries
-Subproject 7d5d207de812ccd7c4648331b00fa936ef0a82c
+Subproject ab6b18161a5b9ccd3588c88233f150fb6c7e2ce
diff --git a/suite/generator.py b/suite/generator.py
index b812b1b5..3302d118 100755
--- a/suite/generator.py
+++ b/suite/generator.py
@@ -10,24 +10,77 @@ import time
unit_test_template = """#!/usr/bin/env python
# This is an auto generated unit test file do not edit directly
import os
+import sys
import unittest
import pickle
import zipfile
import testcommon
-import binaryninja
import api_test
import difflib
+from collections import Counter
+global verbose
+verbose = False
class TestBinaryNinjaAPI(unittest.TestCase):
+ # Returns a tuple of:
+ # bool : Two lists are equal
+ # string : The string diff
+ # Args:
+ # list
+ # list : (compare list one vs list two)
+ # string : anything additional wanted to be printed before the string diff
+ # bool : the ordering of the items in the two lists must be the same
+ def report(self, oracle, test, firstText='', strictOrdering = False):
+ stringDiff = ""
+
+ equality = False
+ if not strictOrdering:
+ equality = (Counter(oracle) == Counter(test))
+ else:
+ equality = (oracle == test)
+
+ if equality:
+ return (True, '')
+ elif not strictOrdering:
+ try:
+ for elem in oracle:
+ test.remove(elem)
+ oracle.remove(elem) # If it's not in the test, it won't get here!
+ except ValueError:
+ pass
+
+ differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
+ skipped_lines = 0
+ for delta in differ.compare(oracle, test):
+ if delta[0] == ' ':
+ skipped_lines += 1
+ continue
+ if skipped_lines > 0:
+ stringDiff += "<---" + str(skipped_lines) + ' same lines--->\\n'
+ skipped_lines = 0
+ delta = delta.replace(\'\\n\', '')
+ stringDiff += delta + \'\\n\'
+
+ stringDiffList = stringDiff.split(\'\\n\')
+
+ if len(stringDiffList) > 10:
+ if not verbose:
+ stringDiff = \'\\n\'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList[:10])
+ stringDiff += \'\\n\\n### And ' + str(len(stringDiffList)) + " more lines, use '-v' to show ###"
+ elif not verbose:
+ stringDiff = \'\\n\'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList)
+ stringDiff = \'\\n\\n\' + firstText + stringDiff
+ return (equality, stringDiff)
+
@classmethod
def setUpClass(self):
self.builder = testcommon.TestBuilder("{3}")
try:
- #Python 2 does not have the encodings option
- self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rUb"), errors="ignore")
+ # Python 2 does not have the encodings option
+ self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rb"), encoding='charmap')
except TypeError:
- self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rU"))
+ self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "r"))
self.verifybuilder = testcommon.VerifyBuilder("{3}")
def run_binary_test(self, testfile):
@@ -38,10 +91,10 @@ class TestBinaryNinjaAPI(unittest.TestCase):
self.assertTrue(os.path.exists(testname + ".pkl"), "Test pickle doesn't exist")
try:
- #Python 2 does not have the encodings option
- binary_oracle = pickle.load(open(testname + ".pkl", "rUb"), errors="ignore")
+ # Python 2 does not have the encodings option
+ binary_oracle = pickle.load(open(testname + ".pkl", "rb"), encoding='charmap')
except TypeError:
- binary_oracle = pickle.load(open(testname + ".pkl", "rU"))
+ binary_oracle = pickle.load(open(testname + ".pkl", "r"))
test_builder = testcommon.BinaryViewTestBuilder(testname, "{3}")
for method in test_builder.methods():
@@ -52,22 +105,16 @@ class TestBinaryNinjaAPI(unittest.TestCase):
result = getattr(test_builder, method).__doc__
result += ":\\n"
- d = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in d.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\\n'
- skipped_lines = 0
- delta = delta.replace('\\n', '')
- result += delta + '\\n'
- self.assertTrue(False, result)
+ report = self.report(oracle, test, result)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
os.unlink(testname)
{1}{2}
if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ if sys.argv[1] == '-v' or sys.argv[1] == '-V' or sys.argv[1] == '--verbose':
+ verbose = True
+
test_suite = unittest.defaultTestLoader.loadTestsFromModule(api_test)
test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestBinaryNinjaAPI))
runner = unittest.TextTestRunner(verbosity=2)
@@ -83,20 +130,8 @@ test_string = """
def {0}(self):
oracle = self.oracle_test_data['{0}']
test = self.builder.{0}()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\\n'
- skipped_lines = 0
- delta = delta.replace('\\n', '')
- result += delta + '\\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
"""
verify_string = """
@@ -108,7 +143,7 @@ verify_string = """
class OracleTestFile:
def __init__(self, filename):
self.f = open(filename + ".pkl", "wb")
- self.pkl = pickle.Pickler(self.f)
+ self.pkl = pickle.Pickler(self.f, protocol=2)
self.filename = filename
self.oracle_test_data = {}
@@ -131,7 +166,7 @@ class UnitTestFile:
self.binary_tests = ""
def close(self):
- self.f.write(self.template.format(self.outdir, self.tests, self.binary_tests, self.test_store).encode('utf-8'))
+ self.f.write(self.template.format(self.outdir, self.tests, self.binary_tests, self.test_store).encode('charmap'))
self.f.close()
def add_verify(self, test_name):
@@ -146,8 +181,6 @@ class UnitTestFile:
quiet = False
-
-
def myprint(stuff):
if not quiet:
print(stuff)
diff --git a/suite/testcommon.py b/suite/testcommon.py
index 1bbc0d47..ef85c053 100644
--- a/suite/testcommon.py
+++ b/suite/testcommon.py
@@ -1,14 +1,54 @@
import tempfile
import pickle
import os
+import sys
import zipfile
import inspect
import binaryninja as binja
from binaryninja.binaryview import BinaryViewType, BinaryView
from binaryninja.filemetadata import FileMetadata
import subprocess
-import traceback
-import types
+import re
+
+
+# Dear people from the future: If you're adding tests or debuging an
+# issue where python2 and python3 are producing different output
+# for the same function and it's a issue of `longs`, run the output
+# through this function. If it's a unicode/bytes issue, fix it in
+# api/python/
+def fixOutput(outputList):
+ # Apply regular expression to detect python2 longs
+ splitList = []
+ for elem in outputList:
+ if isinstance(elem, str):
+ splitList.append(re.split(r"((?<=[\[ ])0x[\da-f]+L|[\d]+L)", elem))
+ else:
+ splitList.append(elem)
+
+ # Resolve application of regular expression
+ result = []
+ for elem in splitList:
+ if isinstance(elem, list):
+ newElem = []
+ for item in elem:
+ if len(item) > 1 and item[-1] == 'L':
+ newElem.append(item[:-1])
+ else:
+ newElem.append(item)
+ result.append(''.join(newElem))
+ else:
+ result.append(elem)
+ return result
+
+
+# Alright so this one is here for Binja functions that output <in set([blah, blah, blah])>
+def fixSet(string):
+ # Apply regular expression
+ splitList = (re.split(r"((?<=<in set\(\[).*(?=\]\)>))", string))
+ if len(splitList) > 1:
+ return splitList[0] + ', '.join(sorted(splitList[1].split(', '))) + splitList[2]
+ else:
+ return string
def get_file_list(test_store):
@@ -16,13 +56,12 @@ def get_file_list(test_store):
for root, dir, files in os.walk(test_store):
for file in files:
all_files.append(os.path.join(root, file))
-
return all_files
def remove_low_confidence(type_string):
low_confidence_types = ["int32_t", "void"]
for lct in low_confidence_types:
- type_string = type_string.replace(lct + " ", '') # done to resolve confidence ties
+ type_string = type_string.replace(lct + " ", '') # done to resolve confidence ties
return type_string
class Builder(object):
@@ -66,15 +105,24 @@ class BinaryViewTestBuilder(Builder):
def test_function_starts(self):
"""Function starts list doesnt match"""
- return ["Function start: " + hex(x.start) for x in self.bv.functions]
+ result = []
+ for x in self.bv.functions:
+ result.append("Function start: " + hex(x.start))
+ return fixOutput(result)
def test_function_symbol_names(self):
"""Function.symbol.name list doesnt match"""
- return ["Symbol: " + x.symbol.name + ' ' + str(x.symbol.type) + ' ' + hex(x.symbol.address) for x in self.bv.functions]
+ result = []
+ for x in self.bv.functions:
+ result.append("Symbol: " + x.symbol.name + ' ' + str(x.symbol.type) + ' ' + hex(x.symbol.address))
+ return fixOutput(result)
def test_function_can_return(self):
"""Function.can_return list doesnt match"""
- return ["function name: " + x.symbol.name + ' type: ' + str(x.symbol.type) + ' address: ' + hex(x.symbol.address) + ' can_return: ' + str(bool(x.can_return)) for x in self.bv.functions]
+ result = []
+ for x in self.bv.functions:
+ result.append("function name: " + x.symbol.name + ' type: ' + str(x.symbol.type) + ' address: ' + hex(x.symbol.address) + ' can_return: ' + str(bool(x.can_return)))
+ return fixOutput(result)
def test_function_basic_blocks(self):
"""Function basic_block list doesnt match (start, end, has_undetermined_outgoing_edges)"""
@@ -85,32 +133,31 @@ class BinaryViewTestBuilder(Builder):
for anno in func.get_block_annotations(bb.start):
bblist.append("basic block {} function annotation: ".format(str(bb)) + str(anno))
bblist.append("basic block {} test get self: ".format(str(bb)) + str(func.get_basic_block_at(bb.start)))
- return bblist
+ return fixOutput(bblist)
def test_function_low_il_basic_blocks(self):
- """"Function low_il_basic_block list doesnt match"""
+ """Function low_il_basic_block list doesnt match"""
ilbblist = []
for func in self.bv.functions:
for bb in func.low_level_il.basic_blocks:
ilbblist.append("LLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing edges: ' + str(len(bb.outgoing_edges)))
- return ilbblist
+ return fixOutput(ilbblist)
def test_function_med_il_basic_blocks(self):
- """"Function med_il_basic_block list doesn't match"""
+ """Function med_il_basic_block list doesn't match"""
ilbblist = []
for func in self.bv.functions:
for bb in func.medium_level_il.basic_blocks:
ilbblist.append("MLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing_edges: ' + str(len(bb.outgoing_edges)))
- return ilbblist
+ return fixOutput(ilbblist)
def test_symbols(self):
- """"Symbols list doesn't match"""
+ """Symbols list doesn't match"""
return ["Symbol: " + str(i) for i in sorted(self.bv.symbols)]
def test_strings(self):
"""Strings list doesn't match"""
- return ["String: " + x.value + ' type: ' + str(x.type) + ' at: ' + hex(x.start) for x in self.bv.strings]
-
+ return fixOutput(["String: " + str(x.value) + ' type: ' + str(x.type) + ' at: ' + hex(x.start) for x in self.bv.strings])
def test_low_il_instructions(self):
"""LLIL instructions produced different output"""
@@ -126,9 +173,7 @@ class BinaryViewTestBuilder(Builder):
retinfo.append("Postfix operands: " + str(ins.postfix_operands))
retinfo.append("SSA form: " + str(ins.ssa_form))
retinfo.append("Non-SSA form: " + str(ins.non_ssa_form))
-
- return retinfo
-
+ return fixOutput(retinfo)
def test_low_il_ssa(self):
"""LLIL ssa produced different output"""
@@ -151,9 +196,7 @@ class BinaryViewTestBuilder(Builder):
retinfo.append("SSA instruction index: " + str(func.get_ssa_instruction_index(tempind)))
retinfo.append("MLIL instruction index: " + str(func.get_medium_level_il_instruction_index(ins.instr_index)))
retinfo.append("Mapped MLIL instruction index: " + str(func.get_mapped_medium_level_il_instruction_index(ins.instr_index)))
-
- return retinfo
-
+ return fixOutput(retinfo)
def test_med_il_instructions(self):
"""MLIL instructions produced different output"""
@@ -165,18 +208,33 @@ class BinaryViewTestBuilder(Builder):
retinfo.append("LLIL: " + str(ins.low_level_il))
retinfo.append("Value: " + str(ins.value))
retinfo.append("Possible values: " + str(ins.possible_values))
- retinfo.append("Branch dependence: " + str(ins.branch_dependence))
- retinfo.append("Prefix operands: " + str(sorted([str(i) for i in ins.prefix_operands])))
- retinfo.append("Postfix operands: " + str(sorted([str(i) for i in ins.postfix_operands])))
- retinfo.append("SSA form: " + str(ins.ssa_form))
- retinfo.append("Non-SSA form" + str(ins.non_ssa_form))
-
- return retinfo
+ retinfo.append("Branch dependence: " + str(sorted(ins.branch_dependence.items())))
+ prefixList = []
+ for i in ins.prefix_operands:
+ if isinstance(i, float) and 'e' in str(i):
+ prefixList.append(str(round(i, 21)))
+ elif isinstance(i, float):
+ prefixList.append(str(round(i, 11)))
+ else:
+ prefixList.append(str(i))
+ retinfo.append("Prefix operands: " + str(sorted(prefixList)))
+ postfixList = []
+ for i in ins.prefix_operands:
+ if isinstance(i, float) and 'e' in str(i):
+ postfixList.append(str(round(i, 21)))
+ elif isinstance(i, float):
+ postfixList.append(str(round(i, 11)))
+ else:
+ postfixList.append(str(i))
+ retinfo.append("Postfix operands: " + str(sorted(postfixList)))
+ retinfo.append("SSA form: " + str(ins.ssa_form))
+ retinfo.append("Non-SSA form" + str(ins.non_ssa_form))
+ return fixOutput(retinfo)
def test_med_il_vars(self):
- """"Function med_il_vars doesn't match"""
+ """Function med_il_vars doesn't match"""
varlist = []
for func in self.bv.functions:
func = func.medium_level_il
@@ -184,14 +242,13 @@ class BinaryViewTestBuilder(Builder):
for instruction in bb:
instruction = instruction.ssa_form
for var in (instruction.vars_read + instruction.vars_written):
- #varlist.append((func.get_var_uses(var), func.get_var_definitions(var)))
if hasattr(var, "var"):
varlist.append("SSA var definition: " + str(func.get_ssa_var_definition(var)))
varlist.append("SSA var uses: " + str(func.get_ssa_var_uses(var)))
varlist.append("SSA var value: " + str(func.get_ssa_var_value(var)))
- varlist.append("SSA var possible values: " + str(instruction.get_ssa_var_possible_values(var)))
+ varlist.append("SSA var possible values: " + fixSet(str(instruction.get_ssa_var_possible_values(var))))
varlist.append("SSA var version: " + str(instruction.get_ssa_var_version))
- return varlist
+ return fixOutput(varlist)
def test_function_stack(self):
"""Function stack produced different output"""
@@ -211,32 +268,26 @@ class BinaryViewTestBuilder(Builder):
funcinfo.append("Sample stack var: " + str(func.get_stack_var_at_frame_offset(0, 0)))
func.delete_user_stack_var(0)
func.delete_auto_stack_var(0)
-
return funcinfo
def test_function_llil(self):
"""Function LLIL produced different output"""
retinfo = []
-
for func in self.bv.functions:
for llilbb in func.llil_basic_blocks:
retinfo.append("LLIL basic block: " + str(llilbb))
for llilins in func.llil_instructions:
retinfo.append("LLIL instruction: " + str(llilins))
-
for mlilbb in func.mlil_basic_blocks:
retinfo.append("MLIL basic block: " + str(mlilbb))
for mlilins in func.mlil_instructions:
retinfo.append("MLIL instruction: " + str(mlilins))
-
for ins in func.instructions:
- retinfo.append("Instructiin: {}: ".format(hex(ins[1])) + ''.join([str(i) for i in ins[0]]))
-
- return retinfo
-
+ retinfo.append("Instruction: {}: ".format(hex(ins[1])) + ''.join([str(i) for i in ins[0]]))
+ return fixOutput(retinfo)
def test_functions_attributes(self):
- """"Function attributes don't match"""
+ """Function attributes don't match"""
funcinfo = []
for func in self.bv.functions:
func.comment = "testcomment " + func.name
@@ -284,9 +335,7 @@ class BinaryViewTestBuilder(Builder):
token = str(token)
token = remove_low_confidence(token)
funcinfo.append("Function {} type token: ".format(func.name) + str(token))
-
-
- return funcinfo
+ return fixOutput(funcinfo)
def test_BinaryView(self):
"""BinaryView produced different results"""
@@ -309,11 +358,12 @@ class BinaryViewTestBuilder(Builder):
retinfo.append("BV entry point: " + hex(self.bv.entry_point))
retinfo.append("BV start: " + hex(self.bv.start))
retinfo.append("BV length: " + hex(len(self.bv)))
- return retinfo
+
+ return fixOutput(retinfo)
class TestBuilder(Builder):
- """ The TestBuilder is for tests that need to be checked against
+ """ The TestBuilder is for tests that need to be checked againsttest_BinaryView
stored oracle data that isn't from a binary. These test are
generated on your local machine then run again on the build
machine to verify correctness.
@@ -335,23 +385,81 @@ class TestBuilder(Builder):
"""unexpected assemble result"""
result = []
# success cases
- result.append("x86 assembly: " + str(binja.Architecture["x86"].assemble("xor eax, eax")))
- result.append("x86_64 assembly: " + str(binja.Architecture["x86_64"].assemble("xor rax, rax")))
- result.append("mips32 assembly: " + str(binja.Architecture["mips32"].assemble("move $ra, $zero")))
- result.append("mipsel32 assembly: " + str(binja.Architecture["mipsel32"].assemble("move $ra, $zero")))
- result.append("armv7 assembly: " + str(binja.Architecture["armv7"].assemble("str r2, [sp, #-0x4]!")))
- result.append("aarch64 assembly: " + str(binja.Architecture["aarch64"].assemble("mov x0, x0")))
- result.append("thumb2 assembly: " + str(binja.Architecture["thumb2"].assemble("ldr r4, [r4]")))
- result.append("thumb2eb assembly: " + str(binja.Architecture["thumb2eb"].assemble("ldr r4, [r4]")))
+
+ strResult = binja.Architecture["x86"].assemble("xor eax, eax")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("x86 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("x86 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["x86_64"].assemble("xor rax, rax")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("x86_64 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("x86_64 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["mips32"].assemble("move $ra, $zero")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("mips32 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("mips32 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["mipsel32"].assemble("move $ra, $zero")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("mipsel32 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("mipsel32 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["armv7"].assemble("str r2, [sp, #-0x4]!")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("armv7 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("armv7 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["aarch64"].assemble("mov x0, x0")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("aarch64 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("aarch64 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["thumb2"].assemble("ldr r4, [r4]")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("thumb2 assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("thumb2 assembly: " + repr(str(strResult)))
+ strResult = binja.Architecture["thumb2eb"].assemble("ldr r4, [r4]")
+ if sys.version_info.major == 3 and not strResult[0] is None:
+ result.append("thumb2eb assembly: " + "'" + str(strResult)[2:-1] + "'")
+ else:
+ result.append("thumb2eb assembly: " + repr(str(strResult)))
+
# fail cases
- result.append("x86 assembly: " + str(binja.Architecture["x86"].assemble("thisisnotaninstruction")))
- result.append("x86_64 assembly: " + str(binja.Architecture["x86_64"].assemble("thisisnotaninstruction")))
- result.append("mips32 assembly: " + str(binja.Architecture["mips32"].assemble("thisisnotaninstruction")))
- result.append("mipsel32 assembly: " + str(binja.Architecture["mipsel32"].assemble("thisisnotaninstruction")))
- result.append("armv7 assembly: " + str(binja.Architecture["armv7"].assemble("thisisnotaninstruction")))
- result.append("aarch64 assembly: " + str(binja.Architecture["aarch64"].assemble("thisisnotaninstruction")))
- result.append("thumb2 assembly: " + str(binja.Architecture["thumb2"].assemble("thisisnotaninstruction")))
- result.append("thumb2eb assembly: " + str(binja.Architecture["thumb2eb"].assemble("thisisnotaninstruction")))
+ try:
+ strResult = binja.Architecture["x86"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'x86'")
+ try:
+ strResult = binja.Architecture["x86_64"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'x86_64'")
+ try:
+ strResult = binja.Architecture["mips32"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'mips32'")
+ try:
+ strResult = binja.Architecture["mipsel32"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'mipsel32'")
+ try:
+ strResult = binja.Architecture["armv7"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'armv7'")
+ try:
+ strResult = binja.Architecture["aarch64"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'aarch64'")
+ try:
+ strResult = binja.Architecture["thumb2"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'thumb2'")
+ try:
+ strResult = binja.Architecture["thumb2eb"].assemble("thisisnotaninstruction")
+ except ValueError:
+ result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'thumb2eb'")
return result
def test_Architecture(self):
@@ -385,8 +493,6 @@ class TestBuilder(Builder):
retinfo.append("Instruction: " + str(ins))
return retinfo
-
-
def test_Function(self):
"""Function produced different result"""
inttype = binja.Type.int(4)
@@ -433,7 +539,6 @@ class TestBuilder(Builder):
def test_Types(self):
"""Types produced different result"""
-
file_name = os.path.join(self.test_store, "helloworld")
bv = binja.BinaryViewType.get_view_of_file(file_name)
preprocessed = binja.preprocess_source("""
@@ -445,7 +550,7 @@ class TestBuilder(Builder):
long long bar1 = 2;
#endif
""")
- source = '\n'.join([i.decode("utf-8") for i in preprocessed[0].split('\n') if not b"#line" in i and len(i) > 0])
+ source = '\n'.join([i.decode('utf-8') for i in preprocessed[0].split(b'\n') if not b'#line' in i and len(i) > 0])
typelist = bv.platform.parse_types_from_source(source)
inttype = binja.Type.int(4)
@@ -464,12 +569,11 @@ class TestBuilder(Builder):
def test_Plugin_bin_info(self):
"""print_syscalls plugin produced different result"""
-
file_name = os.path.join(self.test_store, "helloworld")
self.unpackage_file(file_name)
result = subprocess.Popen(["python", os.path.join(self.examples_dir, "bin_info.py"), file_name], stdout=subprocess.PIPE).communicate()[0]
# normalize line endings and path sep
- return [result.replace(b"\\", b"/").replace(b"\r\n", b"\n")]
+ return [result.replace(b"\\", b"/").replace(b"\r\n", b"\n").decode("charmap")]
def test_linear_disassembly(self):
"""linear_disassembly produced different result"""
@@ -486,7 +590,6 @@ class TestBuilder(Builder):
def test_partial_register_dataflow(self):
"""partial_register_dataflow produced different results"""
-
file_name = os.path.join(self.test_store, "partial_register_dataflow")
self.unpackage_file(file_name)
result = []
@@ -505,7 +608,6 @@ class TestBuilder(Builder):
del bv
finally:
os.unlink(file_name)
-
return result
@@ -524,20 +626,13 @@ class TestBuilder(Builder):
retinfo.append("LLIL second stack element: " + str(ins.get_stack_contents_after(0,1)))
retinfo.append("LLIL possible first stack element: " + str(ins.get_possible_stack_contents(0,1)))
retinfo.append("LLIL possible second stack element: " + str(ins.get_possible_stack_contents_after(0,1)))
-
-
for flag in flag_list:
retinfo.append("LLIL flag {} value at: ".format(flag, hex(ins.address)) + str(ins.get_flag_value(flag)))
retinfo.append("LLIL flag {} value after {}: ".format(flag, hex(ins.address)) + str(ins.get_flag_value_after(flag)))
-
retinfo.append("LLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag)))
retinfo.append("LLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values_after(flag)))
-
- os.unlink(file_name)
-
os.unlink(file_name)
-
- return retinfo
+ return fixOutput(retinfo)
def test_med_il_stack(self):
"""MLIL stack produced different output"""
@@ -555,25 +650,21 @@ class TestBuilder(Builder):
retinfo.append("MLIL second stack element: " + str(ins.get_stack_contents_after(0, 1)))
retinfo.append("MLIL possible first stack element: " + str(ins.get_possible_stack_contents(0, 1)))
retinfo.append("MLIL possible second stack element: " + str(ins.get_possible_stack_contents_after(0, 1)))
-
+
for reg in reg_list:
retinfo.append("MLIL reg {} var at {}: ".format(reg, hex(ins.address)) + str(ins.get_var_for_reg(reg)))
retinfo.append("MLIL reg {} value at {}: ".format(reg, hex(ins.address)) + str(ins.get_reg_value(reg)))
retinfo.append("MLIL reg {} value after {}: ".format(reg, hex(ins.address)) + str(ins.get_reg_value_after(reg)))
- retinfo.append("MLIL reg {} possible value at {}: ".format(reg, hex(ins.address)) + str(ins.get_possible_reg_values(reg)))
- retinfo.append("MLIL reg {} possible value after {}: ".format(reg, hex(ins.address)) + str(ins.get_possible_reg_values_after(reg)))
-
+ retinfo.append("MLIL reg {} possible value at {}: ".format(reg, hex(ins.address)) + fixSet(str(ins.get_possible_reg_values(reg))))
+ retinfo.append("MLIL reg {} possible value after {}: ".format(reg, hex(ins.address)) + fixSet(str(ins.get_possible_reg_values_after(reg))))
for flag in flag_list:
retinfo.append("MLIL flag {} value at: ".format(flag, hex(ins.address)) + str(ins.get_flag_value(flag)))
retinfo.append("MLIL flag {} value after {}: ".format(flag, hex(ins.address)) + str(ins.get_flag_value_after(flag)))
- retinfo.append("MLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag)))
- retinfo.append("MLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag)))
-
+ retinfo.append("MLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + fixSet(str(ins.get_possible_flag_values(flag))))
+ retinfo.append("MLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + fixSet(str(ins.get_possible_flag_values(flag))))
os.unlink(file_name)
-
- return retinfo
-
+ return fixOutput(retinfo)
def test_events(self):
"""Event failure"""
@@ -582,11 +673,9 @@ class TestBuilder(Builder):
bv = binja.BinaryViewType['ELF'].open(file_name)
results = []
-
def simple_complete(self):
results.append("analysis complete")
-
evt = binja.AnalysisCompletionEvent(bv, simple_complete)
class NotifyTest(binja.BinaryDataNotification):
@@ -643,7 +732,13 @@ class TestBuilder(Builder):
def string_found(self, view, string_type, offset, length):
def string_found_complete(self):
- results.append("string found: offset {0} length {1}".format(hex(offset), hex(length)))
+ offset = hex(offset)
+ length = hex(length)
+ if offset[-1] == 'L':
+ offset = offset[:-1]
+ if length[-1] == 'L':
+ length = length[:-1]
+ results.append("string found: offset {0} length {1}".format(offset, length))
evt = binja.AnalysisCompletionEvent(bv, string_found_complete)
def string_removed(self, view, string_type, offset, length):
@@ -666,7 +761,6 @@ class TestBuilder(Builder):
bv.register_notification(test)
sacrificial_addr = 0x84fc
-
type, name = bv.parse_type_string("int foo")
type_id = type.generate_auto_type_id("source", name)
bv.define_type(type_id, name, type)
@@ -684,10 +778,10 @@ class TestBuilder(Builder):
bv.remove(sacrificial_addr, 4)
bv.update_analysis_and_wait()
-
+
bv.unregister_notification(test)
- return sorted(results)
+ return fixOutput(sorted(results))
def unpackage(self, fileName):
testname = None
diff --git a/suite/unit.py b/suite/unit.py
index 9a59b13f..fe2c4b8c 100644
--- a/suite/unit.py
+++ b/suite/unit.py
@@ -1,24 +1,77 @@
#!/usr/bin/env python
# This is an auto generated unit test file do not edit directly
import os
+import sys
import unittest
import pickle
import zipfile
import testcommon
-import binaryninja
import api_test
import difflib
+from collections import Counter
+global verbose
+verbose = False
class TestBinaryNinjaAPI(unittest.TestCase):
+ # Returns a tuple of:
+ # bool : Two lists are equal
+ # string : The string diff
+ # Args:
+ # list
+ # list : (compare list one vs list two)
+ # string : anything additional wanted to be printed before the string diff
+ # bool : the ordering of the items in the two lists must be the same
+ def report(self, oracle, test, firstText='', strictOrdering = False):
+ stringDiff = ""
+
+ equality = False
+ if not strictOrdering:
+ equality = (Counter(oracle) == Counter(test))
+ else:
+ equality = (oracle == test)
+
+ if equality:
+ return (True, '')
+ elif not strictOrdering:
+ try:
+ for elem in oracle:
+ test.remove(elem)
+ oracle.remove(elem) # If it's not in the test, it won't get here!
+ except ValueError:
+ pass
+
+ differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
+ skipped_lines = 0
+ for delta in differ.compare(oracle, test):
+ if delta[0] == ' ':
+ skipped_lines += 1
+ continue
+ if skipped_lines > 0:
+ stringDiff += "<---" + str(skipped_lines) + ' same lines--->\n'
+ skipped_lines = 0
+ delta = delta.replace('\n', '')
+ stringDiff += delta + '\n'
+
+ stringDiffList = stringDiff.split('\n')
+
+ if len(stringDiffList) > 10:
+ if not verbose:
+ stringDiff = '\n'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList[:10])
+ stringDiff += '\n\n### And ' + str(len(stringDiffList)) + " more lines, use '-v' to show ###"
+ elif not verbose:
+ stringDiff = '\n'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList)
+ stringDiff = '\n\n' + firstText + stringDiff
+ return (equality, stringDiff)
+
@classmethod
def setUpClass(self):
self.builder = testcommon.TestBuilder("suite/binaries/test_corpus")
try:
- #Python 2 does not have the encodings option
- self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rUb"), errors="ignore")
+ # Python 2 does not have the encodings option
+ self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rb"), encoding='charmap')
except TypeError:
- self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rU"))
+ self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "r"))
self.verifybuilder = testcommon.VerifyBuilder("suite/binaries/test_corpus")
def run_binary_test(self, testfile):
@@ -29,10 +82,10 @@ class TestBinaryNinjaAPI(unittest.TestCase):
self.assertTrue(os.path.exists(testname + ".pkl"), "Test pickle doesn't exist")
try:
- #Python 2 does not have the encodings option
- binary_oracle = pickle.load(open(testname + ".pkl", "rUb"), errors="ignore")
+ # Python 2 does not have the encodings option
+ binary_oracle = pickle.load(open(testname + ".pkl", "rb"), encoding='charmap')
except TypeError:
- binary_oracle = pickle.load(open(testname + ".pkl", "rU"))
+ binary_oracle = pickle.load(open(testname + ".pkl", "r"))
test_builder = testcommon.BinaryViewTestBuilder(testname, "suite/binaries/test_corpus")
for method in test_builder.methods():
@@ -43,271 +96,93 @@ class TestBinaryNinjaAPI(unittest.TestCase):
result = getattr(test_builder, method).__doc__
result += ":\n"
- d = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in d.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
- self.assertTrue(False, result)
+ report = self.report(oracle, test, result)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
os.unlink(testname)
def test_Architecture(self):
oracle = self.oracle_test_data['test_Architecture']
test = self.builder.test_Architecture()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Architecture_list(self):
oracle = self.oracle_test_data['test_Architecture_list']
test = self.builder.test_Architecture_list()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Assemble(self):
oracle = self.oracle_test_data['test_Assemble']
test = self.builder.test_Assemble()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_BinaryViewType_list(self):
oracle = self.oracle_test_data['test_BinaryViewType_list']
test = self.builder.test_BinaryViewType_list()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Enumeration(self):
oracle = self.oracle_test_data['test_Enumeration']
test = self.builder.test_Enumeration()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Function(self):
oracle = self.oracle_test_data['test_Function']
test = self.builder.test_Function()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Plugin_bin_info(self):
oracle = self.oracle_test_data['test_Plugin_bin_info']
test = self.builder.test_Plugin_bin_info()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Struct(self):
oracle = self.oracle_test_data['test_Struct']
test = self.builder.test_Struct()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_Types(self):
oracle = self.oracle_test_data['test_Types']
test = self.builder.test_Types()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_events(self):
oracle = self.oracle_test_data['test_events']
test = self.builder.test_events()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_linear_disassembly(self):
oracle = self.oracle_test_data['test_linear_disassembly']
test = self.builder.test_linear_disassembly()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_low_il_stack(self):
oracle = self.oracle_test_data['test_low_il_stack']
test = self.builder.test_low_il_stack()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_med_il_stack(self):
oracle = self.oracle_test_data['test_med_il_stack']
test = self.builder.test_med_il_stack()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_partial_register_dataflow(self):
oracle = self.oracle_test_data['test_partial_register_dataflow']
test = self.builder.test_partial_register_dataflow()
- result = ""
- differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
- skipped_lines = 0
- for delta in differ.compare(test, oracle):
- if delta[0] == ' ':
- skipped_lines += 1
- continue
- if skipped_lines > 0:
- result += "<---" + str(skipped_lines) + ' same lines--->\n'
- skipped_lines = 0
- delta = delta.replace('\n', '')
- result += delta + '\n'
-
- self.assertTrue(oracle == test, result)
+ report = self.report(oracle, test)
+ self.assertTrue(report[0], report[1]) # Test does not agree with oracle
def test_verify_BNDB_round_trip(self):
self.assertTrue(self.verifybuilder.test_verify_BNDB_round_trip(), self.test_verify_BNDB_round_trip.__doc__)
@@ -386,6 +261,10 @@ class TestBinaryNinjaAPI(unittest.TestCase):
if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ if sys.argv[1] == '-v' or sys.argv[1] == '-V' or sys.argv[1] == '--verbose':
+ verbose = True
+
test_suite = unittest.defaultTestLoader.loadTestsFromModule(api_test)
test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestBinaryNinjaAPI))
runner = unittest.TextTestRunner(verbosity=2)