diff options
| -rw-r--r-- | python/scriptingprovider.py | 2 | ||||
| -rw-r--r-- | python/types.py | 24 | ||||
| -rw-r--r-- | suite/api_test.py | 113 | ||||
| -rw-r--r-- | suite/testcommon.py | 58 |
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") |
