summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/scriptingprovider.py2
-rw-r--r--python/types.py24
-rw-r--r--suite/api_test.py113
-rw-r--r--suite/testcommon.py58
4 files changed, 185 insertions, 12 deletions
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index a336d99b..092afdb0 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -625,7 +625,7 @@ from binaryninja import *
self.event.set()
def add_input(self, data):
- self.input += data
+ self.input = self.input + data.decode("utf-8")
self.event.set()
def end(self):
diff --git a/python/types.py b/python/types.py
index 4af5d856..f0d4fa94 100644
--- a/python/types.py
+++ b/python/types.py
@@ -527,6 +527,14 @@ class TypeBuilder:
if core is not None:
core.BNFreeTypeBuilder(self._handle)
+ def __eq__(self, other:'TypeBuilder') -> bool:
+ if not isinstance(other, TypeBuilder):
+ raise ValueError(f"Unable compare equality of TypeBuilder and {type(other)}")
+ return self.immutable_copy() == other.immutable_copy()
+
+ def __ne__(self, other:'TypeBuilder') -> bool:
+ return not self.__eq__(other)
+
@property
def handle(self) -> core.BNTypeHandle:
return self.immutable_copy().handle
@@ -740,7 +748,7 @@ class TypeBuilder:
@property
def system_call_number(self) -> Optional[_int]:
- if core.BNTypeBuilderIsSystemCall(self._handle):
+ if not core.BNTypeBuilderIsSystemCall(self._handle):
return None
return core.BNTypeBuilderGetSystemCallNumber(self._handle)
@@ -794,7 +802,7 @@ class CharBuilder(IntegerBuilder):
@classmethod
def create(cls, alternate_name:str="",
platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'CharBuilder':
- handle = core.BNCreateIntegerTypeBuilder(1, False, alternate_name)
+ handle = core.BNCreateIntegerTypeBuilder(1, BoolWithConfidence.get_core_struct(False), alternate_name)
assert handle is not None, "BNCreateIntegerTypeBuilder returned None"
return cls(handle, platform, confidence)
@@ -899,16 +907,15 @@ class FunctionBuilder(TypeBuilder):
self.child = value
def append(self, type:Union[SomeType, FunctionParameter], name:str=""):
- params = self.parameters
if isinstance(type, FunctionParameter):
- self.parameters.append(type.mutable_copy())
+ self.parameters = [*self.parameters, type]
else:
- self.parameters.append(FunctionParameter(type.mutable_copy(), name))
- self.params = params
+ self.parameters = [*self.parameters, FunctionParameter(type, name)]
@property
def calling_convention(self) -> 'callingconvention.CallingConvention':
- return callingconvention.CallingConvention(core.BNNewCallingConventionReference(core.BNGetTypeBuilderCallingConvention(self._handle)))
+ cc = core.BNGetTypeBuilderCallingConvention(self._handle)
+ return callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc.convention))
@property
def can_return(self) -> BoolWithConfidence:
@@ -1244,7 +1251,8 @@ class EnumerationBuilder(TypeBuilder):
def immutable_copy(self) -> 'EnumerationType':
enum_handle = core.BNFinalizeEnumerationBuilder(self.enum_builder_handle)
assert enum_handle is not None, "core.BNFinalizeEnumerationBuilder returned None"
- handle = core.BNCreateEnumerationType(None, enum_handle, self.width, self.signed)
+ _signed = BoolWithConfidence.get_core_struct(self.signed)
+ handle = core.BNCreateEnumerationType(None, enum_handle, self.width, _signed)
assert handle is not None, "core.BNCreateEnumerationType returned None"
return EnumerationType(handle, self.platform, self.confidence)
diff --git a/suite/api_test.py b/suite/api_test.py
index 3181d8cf..4fd07b7c 100644
--- a/suite/api_test.py
+++ b/suite/api_test.py
@@ -9,6 +9,10 @@ from binaryninja.demangle import demangle_gnu3, demangle_ms, get_qualified_name
from binaryninja.architecture import Architecture
from binaryninja.pluginmanager import RepositoryManager
from binaryninja.platform import Platform
+from binaryninja.function import Function
+from binaryninja.types import (Type, TypeBuilder, FunctionParameter, BoolWithConfidence, EnumerationBuilder, NamedTypeReferenceBuilder,
+ IntegerBuilder, CharBuilder, FloatBuilder, WideCharBuilder, PointerBuilder, ArrayBuilder, FunctionBuilder, StructureBuilder,
+ StructureMember)
class SettingsAPI(unittest.TestCase):
@classmethod
@@ -413,4 +417,111 @@ class TypeParserTest(unittest.TestCase):
s = result.types[name]
assert len(s) == size, f"Structure property: 'size' {size} incorrect for {definition} got {len(s)} instead"
assert s.alignment == alignment, f"Structure property: 'alignment' {alignment} incorrect for {definition} got {s.alignment} instead"
- assert len(s.members) == members, f"Structure property: 'members' {members} incorrect for {definition} got {len(s.members)} instead" \ No newline at end of file
+ assert len(s.members) == members, f"Structure property: 'members' {members} incorrect for {definition} got {len(s.members)} instead"
+
+class TypeBuilderTest(unittest.TestCase):
+ def setUp(self) -> None:
+ self.arch = Architecture['x86_64']
+ self.plat = Platform['x86_64']
+ self.cc = self.plat.calling_conventions[0]
+
+ def test_builder_mutability_round_trip(self):
+ ib = TypeBuilder.int(4)
+ ib.const = True
+ ib.volatile = False
+ ib.alternate_name = "billy bob"
+ ib.signed = True
+ assert ib.const
+ assert not ib.volatile
+ assert ib.alternate_name == "billy bob"
+ assert ib.signed
+ assert len(ib) == 4
+ assert ib == ib.immutable_copy().mutable_copy(), "IntegerBuilder failed to round trip mutability"
+
+ b = TypeBuilder.char("my_char")
+ b.const = True
+ b.volatile = False
+ assert b.alternate_name == "my_char"
+ b.alternate_name = "my_char2"
+ assert b.const
+ assert not b.volatile
+ assert b.alternate_name == "my_char2"
+ assert b == b.immutable_copy().mutable_copy(), "CharBuilder failed to round trip mutability"
+
+
+ b = TypeBuilder.float(4, "half")
+ b.const = True
+ b.volatile = False
+ assert b.const
+ assert not b.volatile
+ assert b.alternate_name == "half"
+ assert b == b.immutable_copy().mutable_copy(), "FloatBuilder failed to round trip mutability"
+
+ b = TypeBuilder.wide_char(4, "wchar32_t")
+ b.const = True
+ b.volatile = False
+ assert b.const
+ assert not b.volatile
+ assert b.alternate_name == "wchar32_t"
+ assert b == b.immutable_copy().mutable_copy(), "WideCharBuilder failed to round trip mutability"
+
+ b = TypeBuilder.pointer(self.arch, ib, 4)
+ b.const = True
+ b.volatile = False
+ assert ib.immutable_copy() == b.immutable_target
+ assert ib == b.target
+ assert ib.immutable_copy() == b.child.immutable_copy()
+ assert b == b.immutable_copy().mutable_copy(), "PointerBuilder failed to round trip mutability"
+ pb = b
+
+ b = TypeBuilder.void()
+ assert b == b.immutable_copy().mutable_copy(), "VoidBuilder failed to round trip mutability"
+ vb = b
+
+ b = TypeBuilder.bool()
+ assert b == b.immutable_copy().mutable_copy(), "VoidBuilder failed to round trip mutability"
+ bb = b
+
+ b = TypeBuilder.function(vb, [FunctionParameter(pb, "arg1")], self.cc)
+ assert b.system_call_number is None
+ b.system_call_number = 1
+ assert b.system_call_number == 1
+ b.clear_system_call()
+ assert b.system_call_number is None
+ b.system_call_number = 1
+
+ assert b == b.immutable_copy().mutable_copy(), "FunctionBuilder failed to round trip mutability"
+ assert b.immutable_return_value == vb.immutable_copy()
+ assert b.return_value == vb
+ b.return_value = b
+ b.append(bb)
+ b.append(FunctionParameter(pb, "arg3"))
+ assert b.calling_convention == self.cc
+ assert b.can_return
+ b.can_return = False
+ assert not b.can_return
+ assert b.stack_adjust == 0
+ assert len(b.parameters) == 3
+ assert b.parameters[0].type == pb.immutable_copy()
+ assert b.parameters[0].name == "arg1"
+ assert b.parameters[1].type == bb.immutable_copy()
+ assert b.parameters[1].name == ""
+ assert b.parameters[2].type == pb.immutable_copy()
+ assert b.parameters[2].name == "arg3"
+ assert b.stack_adjust.value == 0
+ assert not b.variable_arguments
+ b.parameters = [FunctionParameter(pb, "arg1")]
+ assert b.parameters[0].type == pb.immutable_copy()
+ assert b.parameters[0].name == "arg1"
+ assert len(b.parameters) == 1
+
+
+ b = TypeBuilder.structure([(ib, "name")], False)
+ assert b.alignment == 4
+
+ b = TypeBuilder.array(pb, 4)
+ assert len(b) == len(pb) * 4
+ assert b.count == 4
+ assert b.element_type == pb.immutable_copy()
+
+ b = TypeBuilder.structure([StructureMember()]) \ No newline at end of file
diff --git a/suite/testcommon.py b/suite/testcommon.py
index ac31e668..631c626e 100644
--- a/suite/testcommon.py
+++ b/suite/testcommon.py
@@ -10,8 +10,10 @@ from binaryninja.filemetadata import FileMetadata
from binaryninja.datarender import DataRenderer
from binaryninja.function import InstructionTextToken, DisassemblyTextLine
from binaryninja.enums import InstructionTextTokenType, FindFlag,\
- FunctionGraphType
-from binaryninja.types import Type
+ FunctionGraphType, NamedTypeReferenceClass, ReferenceType
+from binaryninja.types import (Type, BoolWithConfidence, EnumerationBuilder, NamedTypeReferenceBuilder,
+ IntegerBuilder, CharBuilder, FloatBuilder, WideCharBuilder, PointerBuilder, ArrayBuilder, FunctionBuilder, StructureBuilder,
+ EnumerationBuilder, NamedTypeReferenceBuilder)
import subprocess
import re
@@ -804,6 +806,58 @@ class TestBuilder(Builder):
finally:
self.delete_package("helloworld")
+ def test_TypeBuilders_and_Types(self):
+ """Test TypeBuilders"""
+ file_name = self.unpackage_file("helloworld")
+ try:
+ with binja.open_view(file_name) as bv:
+ with binja.StructureBuilder.builder(bv, 'Foo') as s:
+ s.packed = True
+ s.append(Type.int(2))
+ s.append(Type.int(4))
+ s.append(Type.void())
+ s.append(Type.bool())
+ s.append(Type.char())
+ s.append(Type.char("char_alt_name"))
+ s.append(Type.float(2), "half")
+ s.append(Type.float(4) )
+ s.append(Type.float(8))
+ s.append(Type.float(16))
+ s.append(Type.wide_char(4, "wchar32_t"))
+ s.append(Type.structure_type(binja.StructureBuilder.create([Type.int(1)])))
+ s.append(Type.named_type(NamedTypeReferenceBuilder.create(NamedTypeReferenceClass.UnknownNamedTypeClass, "id", "name")))
+ s.append(Type.named_type_from_type_and_id("id2", ["qualified", "name"]))
+ s.append(Type.generate_named_type_reference("guid", [b"byte", b"name"]))
+ s.append(Type.enumeration_type(bv.arch, EnumerationBuilder.create([("Member1", 1)])))
+ try:
+ Type.pointer(None, None) # test the failure case
+ except binja.types.TypeCreateException as tce:
+ pass
+ s.append(Type.pointer_of_width(8, Type.int(4), BoolWithConfidence(True, 255), BoolWithConfidence(False, 255), ReferenceType.RValueReferenceType))
+ s.append(Type.array(Type.int(4), 4))
+ s.append(Type.structure([(Type.int(4), "field1")]))
+ s.append(Type.enumeration(bv.arch, [binja.types.EnumerationMember("Mem-1", 1), binja.types.EnumerationMember("Mem-2")]))
+ s.append(Type.enumeration(bv.arch, [binja.types.EnumerationMember("Mem2-1", 1), binja.types.EnumerationMember("Mem2-2")], 2))
+ s.append(Type.enumeration(bv.arch, [binja.types.EnumerationMember("Mem3-1", 1), binja.types.EnumerationMember("Mem3-2")], 2, True))
+ s.append(Type.enumeration(bv.arch, None))
+ tid = Type.generate_auto_demangled_type_id("auto_demangled_tid")
+ tid_source = Type.get_auto_demangled_type_id_source()
+ s.append(Type.named_type_reference(NamedTypeReferenceClass.UnknownNamedTypeClass, "Someothername", tid, 4, 4, True, True))
+ try:
+ Type.int(4).name
+ assert False, "trying to access name of integer succeeded when it shouldn't have"
+ except NotImplementedError:
+ pass
+
+ members = s.members
+ s = bv.types['Foo']
+ assert members == s.members
+ assert const == s.const
+ assert volatile == s.volatile
+ return str(s.members)
+ finally:
+ self.delete_package("helloworld")
+
def test_Plugin_bin_info(self):
"""print_syscalls plugin produced different result"""
file_name = self.unpackage_file("helloworld")