diff options
| -rw-r--r-- | PythonAPIDocumentation.md | 9 | ||||
| -rw-r--r-- | python/function.py | 224 | ||||
| -rw-r--r-- | suite/api_test.py | 724 |
3 files changed, 638 insertions, 319 deletions
diff --git a/PythonAPIDocumentation.md b/PythonAPIDocumentation.md index 95e5e9dd..61f59251 100644 --- a/PythonAPIDocumentation.md +++ b/PythonAPIDocumentation.md @@ -155,10 +155,11 @@ DataVariable objects have been greatly enhanced in Binary Ninja 3.0. In the core Prior to 3.0 a frequent question was: "Through the API how do you set the name of a DataVariable?" The answer was always "You don't, instead create a symbol at that location." This is the same way function names are handled. Although this abstraction serves us well it doesn't make for an intuitive API, thus DataVariable now has a convenient method for setting the variables name and name. ```python -data_var = bv.get_data_var_at(here) -data_var.name -data_var.name = 'foobar' -data_var.name +>>> data_var = bv.get_data_var_at(here) +>>> data_var.name + +>>> data_var.name = 'foobar' +>>> data_var.name 'foobar' ``` Or if you prefer to give the DataVariable a more complete symbol. diff --git a/python/function.py b/python/function.py index 2e93ac2e..03dc6ddc 100644 --- a/python/function.py +++ b/python/function.py @@ -695,7 +695,7 @@ class Function: return tag def remove_user_address_tag( - self, addr: int, tag: 'binaryview.TagType', arch: Optional['architecture.Architecture'] = None + self, addr: int, tag: 'binaryview.Tag', arch: Optional['architecture.Architecture'] = None ) -> None: """ ``remove_user_address_tag`` removes a Tag object at a given address. @@ -713,7 +713,7 @@ class Function: core.BNRemoveUserAddressTag(self.handle, arch.handle, addr, tag.handle) def add_auto_address_tag( - self, addr: int, tag: 'binaryview.TagType', arch: Optional['architecture.Architecture'] = None + self, addr: int, tag: 'binaryview.Tag', arch: Optional['architecture.Architecture'] = None ) -> None: """ ``add_auto_address_tag`` adds an already-created Tag object at a given address. @@ -1611,11 +1611,13 @@ class Function: count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILInstructionsForAddress(self.handle, arch.handle, addr, count) assert instrs is not None, "core.BNGetLowLevelILInstructionsForAddress returned None" - result = [] - for i in range(0, count.value): - result.append(self.llil[instrs[i]]) - core.BNFreeILInstructionList(instrs) - return result + try: + result = [] + for i in range(0, count.value): + result.append(self.llil[instrs[i]]) + return result + finally: + core.BNFreeILInstructionList(instrs) def get_low_level_il_exits_at(self, addr: int, arch: Optional['architecture.Architecture'] = None) -> List[int]: if arch is None: @@ -1625,11 +1627,13 @@ class Function: count = ctypes.c_ulonglong() exits = core.BNGetLowLevelILExitsForInstruction(self.handle, arch.handle, addr, count) assert exits is not None, "core.BNGetLowLevelILExitsForInstruction returned None" - result = [] - for i in range(0, count.value): - result.append(exits[i]) - core.BNFreeILInstructionList(exits) - return result + try: + result = [] + for i in range(0, count.value): + result.append(exits[i]) + return result + finally: + core.BNFreeILInstructionList(exits) def get_reg_value_at( self, addr: int, reg: 'architecture.RegisterType', arch: Optional['architecture.Architecture'] = None @@ -1666,15 +1670,17 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetAutoAddressTagReferences(self.handle, count) assert tags is not None, "core.BNGetAutoAddressTagReferences returned None" - result = [] - for i in range(0, count.value): - arch = architecture.CoreArchitecture._from_cache(tags[i].arch) - tag_ref = core.BNNewTagReference(tags[i].tag) - assert tag_ref is not None, "core.BNNewTagReference returned None" - tag = binaryview.Tag(tag_ref) - result.append((arch, tags[i].addr, tag)) - core.BNFreeTagReferences(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + arch = architecture.CoreArchitecture._from_cache(tags[i].arch) + tag_ref = core.BNNewTagReference(tags[i].tag) + assert tag_ref is not None, "core.BNNewTagReference returned None" + tag = binaryview.Tag(tag_ref) + result.append((arch, tags[i].addr, tag)) + return result + finally: + core.BNFreeTagReferences(tags, count.value) @property def user_address_tags(self): @@ -1687,15 +1693,17 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetUserAddressTagReferences(self.handle, count) assert tags is not None, "core.BNGetUserAddressTagReferences returned" - result = [] - for i in range(0, count.value): - arch = architecture.CoreArchitecture._from_cache(tags[i].arch) - tag_ref = core.BNNewTagReference(tags[i].tag) - assert tag_ref is not None, "core.BNNewTagReference returned None" - tag = binaryview.Tag(tag_ref) - result.append((arch, tags[i].addr, tag)) - core.BNFreeTagReferences(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + arch = architecture.CoreArchitecture._from_cache(tags[i].arch) + tag_ref = core.BNNewTagReference(tags[i].tag) + assert tag_ref is not None, "core.BNNewTagReference returned None" + tag = binaryview.Tag(tag_ref) + result.append((arch, tags[i].addr, tag)) + return result + finally: + core.BNFreeTagReferences(tags, count.value) def get_reg_value_after( self, addr: int, reg: 'architecture.RegisterType', arch: Optional['architecture.Architecture'] = None @@ -1736,13 +1744,15 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetAutoAddressTags(self.handle, arch.handle, addr, count) assert tags is not None, "core.BNGetAutoAddressTags returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(tags[i]) - assert tag_ref is not None, "core.BNNewTagReference returned None" - result.append(binaryview.Tag(tag_ref)) - core.BNFreeTagList(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(tags[i]) + assert tag_ref is not None, "core.BNNewTagReference returned None" + result.append(binaryview.Tag(tag_ref)) + return result + finally: + core.BNFreeTagList(tags, count.value) def get_user_address_tags_at(self, addr, arch=None): """ @@ -1759,15 +1769,17 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetUserAddressTags(self.handle, arch.handle, addr, count) assert tags is not None, "core.BNGetUserAddressTags returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(tags[i]) - assert tag_ref is not None, "core.BNNewTagReference returned None" - result.append(binaryview.Tag(tag_ref)) - core.BNFreeTagList(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(tags[i]) + assert tag_ref is not None, "core.BNNewTagReference returned None" + result.append(binaryview.Tag(tag_ref)) + return result + finally: + core.BNFreeTagList(tags, count.value) - def get_address_tags_of_type(self, addr, tag_type, arch=None): + def get_address_tags_of_type(self, addr: 'architecture.Architecture', tag_type: 'binaryview.TagType', arch=None): """ ``get_address_tags_of_type`` gets a list of all Tags in the function at a given address with a given type. @@ -1783,15 +1795,19 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) assert tags is not None, "core.BNGetAddressTagsOfType returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(tags[i]) - assert tag_ref is not None, "core.BNNewTagReference returned None" - result.append(binaryview.Tag(tag_ref)) - core.BNFreeTagList(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(tags[i]) + assert tag_ref is not None, "core.BNNewTagReference returned None" + result.append(binaryview.Tag(tag_ref)) + return result + finally: + core.BNFreeTagList(tags, count.value) - def get_auto_address_tags_of_type(self, addr, tag_type, arch=None): + def get_auto_address_tags_of_type( + self, addr: int, tag_type: 'binaryview.TagType', arch: 'architecture.Architecture' = None + ): """ ``get_auto_address_tags_of_type`` gets a list of all auto-defined Tags in the function at a given address with a given type. @@ -1807,15 +1823,19 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetAutoAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) assert tags is not None, "core.BNGetAutoAddressTagsOfType returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(tags[i]) - assert tag_ref is not None, "core.BNNewTagReference returned None" - result.append(binaryview.Tag(tag_ref)) - core.BNFreeTagList(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(tags[i]) + assert tag_ref is not None, "core.BNNewTagReference returned None" + result.append(binaryview.Tag(tag_ref)) + return result + finally: + core.BNFreeTagList(tags, count.value) - def get_user_address_tags_of_type(self, addr, tag_type, arch=None): + def get_user_address_tags_of_type( + self, addr: int, tag_type: 'binaryview.TagType', arch: 'architecture.Architecture' = None + ): """ ``get_user_address_tags_of_type`` gets a list of all user Tags in the function at a given address with a given type. @@ -1831,15 +1851,19 @@ class Function: count = ctypes.c_ulonglong() tags = core.BNGetUserAddressTagsOfType(self.handle, arch.handle, addr, tag_type.handle, count) assert tags is not None, "core.BNGetUserAddressTagsOfType returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(tags[i]) - assert tag_ref is not None, "core.BNNewTagReference returned None" - result.append(binaryview.Tag(tag_ref)) - core.BNFreeTagList(tags, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(tags[i]) + assert tag_ref is not None, "core.BNNewTagReference returned None" + result.append(binaryview.Tag(tag_ref)) + return result + finally: + core.BNFreeTagList(tags, count.value) - def get_address_tags_in_range(self, address_range, arch=None): + def get_address_tags_in_range( + self, address_range: 'variable.AddressRange', arch: 'architecture.Architecture' = None + ) -> List[Tuple['architecture.Architecture', int, 'binaryview.Tag']]: """ ``get_address_tags_in_range`` gets a list of all Tags in the function at a given address. Range is inclusive at the start, exclusive at the end. @@ -1855,16 +1879,20 @@ class Function: count = ctypes.c_ulonglong() refs = core.BNGetAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) assert refs is not None, "core.BNGetAddressTagsInRange returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(refs[i].tag) - assert tag_ref is not None, "core.BNNewTagReference returned None" - tag = binaryview.Tag(tag_ref) - result.append((arch, refs[i].addr, tag)) - core.BNFreeTagReferences(refs, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(refs[i].tag) + assert tag_ref is not None, "core.BNNewTagReference returned None" + tag = binaryview.Tag(tag_ref) + result.append((arch, refs[i].addr, tag)) + return result + finally: + core.BNFreeTagReferences(refs, count.value) - def get_auto_address_tags_in_range(self, address_range, arch=None): + def get_auto_address_tags_in_range( + self, address_range: 'variable.AddressRange', arch: 'architecture.Architecture' = None + ) -> List[Tuple['architecture.Architecture', int, 'binaryview.Tag']]: """ ``get_auto_address_tags_in_range`` gets a list of all auto-defined Tags in the function at a given address. Range is inclusive at the start, exclusive at the end. @@ -1880,16 +1908,20 @@ class Function: count = ctypes.c_ulonglong() refs = core.BNGetAutoAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) assert refs is not None, "core.BNGetAutoAddressTagsInRange returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(refs[i].tag) - assert tag_ref is not None, "core.BNNewTagReference returned None" - tag = binaryview.Tag(tag_ref) - result.append((arch, refs[i].addr, tag)) - core.BNFreeTagReferences(refs, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(refs[i].tag) + assert tag_ref is not None, "core.BNNewTagReference returned None" + tag = binaryview.Tag(tag_ref) + result.append((arch, refs[i].addr, tag)) + return result + finally: + core.BNFreeTagReferences(refs, count.value) - def get_user_address_tags_in_range(self, address_range, arch=None): + def get_user_address_tags_in_range( + self, address_range: 'variable.AddressRange', arch: 'architecture.Architecture' = None + ) -> List[Tuple['architecture.Architecture', int, 'binaryview.Tag']]: """ ``get_user_address_tags_in_range`` gets a list of all user Tags in the function at a given address. Range is inclusive at the start, exclusive at the end. @@ -1905,14 +1937,16 @@ class Function: count = ctypes.c_ulonglong() refs = core.BNGetUserAddressTagsInRange(self.handle, arch.handle, address_range.start, address_range.end, count) assert refs is not None, "core.BNGetUserAddressTagsInRange returned None" - result = [] - for i in range(0, count.value): - tag_ref = core.BNNewTagReference(refs[i].tag) - assert tag_ref is not None, "core.BNNewTagReference returned None" - tag = binaryview.Tag(tag_ref) - result.append((arch, refs[i].addr, tag)) - core.BNFreeTagReferences(refs, count.value) - return result + try: + result = [] + for i in range(0, count.value): + tag_ref = core.BNNewTagReference(refs[i].tag) + assert tag_ref is not None, "core.BNNewTagReference returned None" + tag = binaryview.Tag(tag_ref) + result.append((arch, refs[i].addr, tag)) + return result + finally: + core.BNFreeTagReferences(refs, count.value) def get_stack_contents_at( self, addr: int, offset: int, size: int, arch: Optional['architecture.Architecture'] = None diff --git a/suite/api_test.py b/suite/api_test.py index e7f6a325..e6de3fa5 100644 --- a/suite/api_test.py +++ b/suite/api_test.py @@ -10,23 +10,31 @@ from binaryninja.architecture import Architecture from binaryninja.pluginmanager import RepositoryManager from binaryninja.platform import Platform from binaryninja.function import Function -from binaryninja.enums import (StructureVariant, NamedTypeReferenceClass, MemberAccess, - MemberScope, ReferenceType, VariableSourceType, - SymbolBinding, SymbolType, TokenEscapingType) -from binaryninja.types import (QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, OffsetWithConfidence, BoolWithConfidence, EnumerationBuilder, NamedTypeReferenceBuilder, - StructureBuilder, StructureMember, IntegerType, StructureType, Symbol, NameSpace, MutableTypeBuilder, - NamedTypeReferenceType) +from binaryninja.enums import ( + StructureVariant, NamedTypeReferenceClass, MemberAccess, MemberScope, ReferenceType, VariableSourceType, + SymbolBinding, SymbolType, TokenEscapingType +) + +from binaryninja.types import ( + QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, OffsetWithConfidence, BoolWithConfidence, + EnumerationBuilder, NamedTypeReferenceBuilder, StructureBuilder, StructureMember, IntegerType, StructureType, + Symbol, NameSpace, MutableTypeBuilder, NamedTypeReferenceType +) +from binaryninja.function import * +from binaryninja.basicblock import * +from binaryninja.binaryview import * from binaryninja.variable import (VariableNameAndType) import zipfile class Apparatus: test_store = "binaries/test_corpus" + def __init__(self, filename): self.filename = filename if not os.path.exists(self.path): with zipfile.ZipFile(self.path + ".zip", "r") as zf: - zf.extractall(path = os.path.dirname(__file__)) + zf.extractall(path=os.path.dirname(__file__)) assert os.path.exists(self.path) self.bv = BinaryViewType.get_view_of_file(os.path.relpath(self.path)) @@ -46,6 +54,16 @@ class Apparatus: pass +class TestWithBinaryView(unittest.TestCase): + file_name = "helloworld" + + def setUp(self): + self.apparatus = Apparatus(self.file_name) + self.bv = self.apparatus.bv + self.arch = self.bv.arch + self.plat = self.bv.platform + + class SettingsAPI(unittest.TestCase): @classmethod def setUpClass(cls): @@ -69,32 +87,73 @@ class SettingsAPI(unittest.TestCase): assert settings.contains("analysis.linearSweep.autorun"), "test_settings_defaults failed" assert settings.contains("analysis.unicode.blocks"), "test_settings_defaults failed" assert settings.contains("network.downloadProviderName"), "test_settings_defaults failed" - assert settings.get_bool_with_scope("analysis.linearSweep.autorun", scope=SettingsScope.SettingsDefaultScope)[0], "test_settings_defaults failed" - assert settings.get_bool_with_scope("analysis.linearSweep.autorun", scope=SettingsScope.SettingsDefaultScope)[1] == SettingsScope.SettingsDefaultScope, "test_settings_defaults failed" + assert settings.get_bool_with_scope("analysis.linearSweep.autorun", scope=SettingsScope.SettingsDefaultScope + )[0], "test_settings_defaults failed" + assert settings.get_bool_with_scope("analysis.linearSweep.autorun", scope=SettingsScope.SettingsDefaultScope + )[1] == SettingsScope.SettingsDefaultScope, "test_settings_defaults failed" def test_settings_registration(self): settings = Settings("test") assert not settings.contains("testGroup.testSetting"), "test_settings_registration failed" assert settings.register_group("testGroup", "Title"), "test_settings_registration failed" - assert settings.register_setting("testGroup.testSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "testSetting"}'), "test_settings_registration failed" + assert settings.register_setting( + "testGroup.testSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "testSetting"}' + ), "test_settings_registration failed" assert settings.contains("testGroup.testSetting"), "test_settings_registration failed" def test_settings_usage(self): settings = Settings("test") assert not settings.contains("testGroup.testSetting"), "test_settings_types failed" assert settings.register_group("testGroup", "Title"), "test_settings_types failed" - assert not settings.register_setting("testGroup.boolSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "boolean", "id" : "boolSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.boolSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting"}'), "test_settings_types failed" - assert not settings.register_setting("testGroup.doubleSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "number", "id" : "doubleSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.doubleSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "number", "id" : "doubleSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.integerSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "number", "id" : "integerSetting"}'), "test_settings_types failed" - assert not settings.register_setting("testGroup.stringSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "string", "id" : "stringSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.stringSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : "value", "type" : "string", "id" : "stringSetting"}'), "test_settings_types failed" - assert not settings.register_setting("testGroup.stringListSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "array", "elementType" : "string", "id" : "stringListSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.stringListSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : ["value1", "value2"], "type" : "array", "elementType" : "string", "id" : "stringListSetting"}'), "test_settings_types failed" - assert settings.register_setting("testGroup.ignoreResourceBoolSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsResourceScope"]}'), "test_settings_types failed" - assert settings.register_setting("testGroup.ignoreUserBoolSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsUserScope"]}'), "test_settings_types failed" - assert settings.register_setting("testGroup.readOnlyBoolSetting", '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsResourceScope", "SettingsUserScope"]}'), "test_settings_types failed" + assert not settings.register_setting( + "testGroup.boolSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "boolean", "id" : "boolSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.boolSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting"}' + ), "test_settings_types failed" + assert not settings.register_setting( + "testGroup.doubleSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "number", "id" : "doubleSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.doubleSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "number", "id" : "doubleSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.integerSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "number", "id" : "integerSetting"}' + ), "test_settings_types failed" + assert not settings.register_setting( + "testGroup.stringSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : 500, "type" : "string", "id" : "stringSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.stringSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : "value", "type" : "string", "id" : "stringSetting"}' + ), "test_settings_types failed" + assert not settings.register_setting( + "testGroup.stringListSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "array", "elementType" : "string", "id" : "stringListSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.stringListSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : ["value1", "value2"], "type" : "array", "elementType" : "string", "id" : "stringListSetting"}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.ignoreResourceBoolSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsResourceScope"]}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.ignoreUserBoolSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsUserScope"]}' + ), "test_settings_types failed" + assert settings.register_setting( + "testGroup.readOnlyBoolSetting", + '{"description" : "Test description.", "title" : "Test Title", "default" : true, "type" : "boolean", "id" : "boolSetting", "ignore" : ["SettingsResourceScope", "SettingsUserScope"]}' + ), "test_settings_types failed" assert settings.contains("testGroup.boolSetting"), "test_settings_types failed" assert settings.contains("testGroup.doubleSetting"), "test_settings_types failed" @@ -106,43 +165,75 @@ class SettingsAPI(unittest.TestCase): assert settings.get_double("testGroup.doubleSetting") == 500, "test_settings_types failed" assert settings.get_integer("testGroup.integerSetting") == 500, "test_settings_types failed" assert settings.get_string("testGroup.stringSetting") == "value", "test_settings_types failed" - assert settings.get_string_list("testGroup.stringListSetting") == ["value1", "value2"], "test_settings_types failed" + assert settings.get_string_list("testGroup.stringListSetting") == [ + "value1", "value2" + ], "test_settings_types failed" assert settings.set_bool("testGroup.boolSetting", False), "test_settings_types failed" assert settings.set_double("testGroup.doubleSetting", 700), "test_settings_types failed" assert settings.set_integer("testGroup.integerSetting", 700), "test_settings_types failed" assert settings.set_string("testGroup.stringSetting", "value_user"), "test_settings_types failed" - assert settings.set_string_list("testGroup.stringListSetting", ["value3", "value4"]), "test_settings_types failed" + assert settings.set_string_list( + "testGroup.stringListSetting", ["value3", "value4"] + ), "test_settings_types failed" assert settings.get_bool("testGroup.boolSetting") == False, "test_settings_types failed" assert settings.get_double("testGroup.doubleSetting") == 700, "test_settings_types failed" assert settings.get_integer("testGroup.integerSetting") == 700, "test_settings_types failed" assert settings.get_string("testGroup.stringSetting") == "value_user", "test_settings_types failed" - assert settings.get_string_list("testGroup.stringListSetting") == ["value3", "value4"], "test_settings_types failed" + assert settings.get_string_list("testGroup.stringListSetting") == [ + "value3", "value4" + ], "test_settings_types failed" - assert settings.get_bool_with_scope("testGroup.boolSetting", scope=SettingsScope.SettingsDefaultScope)[0] == True, "test_settings_types failed" - assert settings.get_double_with_scope("testGroup.doubleSetting", scope=SettingsScope.SettingsDefaultScope)[0] == 500, "test_settings_types failed" - assert settings.get_integer_with_scope("testGroup.integerSetting", scope=SettingsScope.SettingsDefaultScope)[0] == 500, "test_settings_types failed" - assert settings.get_string_with_scope("testGroup.stringSetting", scope=SettingsScope.SettingsDefaultScope)[0] == "value", "test_settings_types failed" - assert settings.get_string_list_with_scope("testGroup.stringListSetting", scope=SettingsScope.SettingsDefaultScope)[0] == ["value1", "value2"], "test_settings_types failed" + assert settings.get_bool_with_scope("testGroup.boolSetting", scope=SettingsScope.SettingsDefaultScope + )[0] == True, "test_settings_types failed" + assert settings.get_double_with_scope("testGroup.doubleSetting", scope=SettingsScope.SettingsDefaultScope + )[0] == 500, "test_settings_types failed" + assert settings.get_integer_with_scope("testGroup.integerSetting", scope=SettingsScope.SettingsDefaultScope + )[0] == 500, "test_settings_types failed" + assert settings.get_string_with_scope("testGroup.stringSetting", scope=SettingsScope.SettingsDefaultScope + )[0] == "value", "test_settings_types failed" + assert settings.get_string_list_with_scope( + "testGroup.stringListSetting", scope=SettingsScope.SettingsDefaultScope + )[0] == ["value1", "value2"], "test_settings_types failed" - assert settings.get_bool_with_scope("testGroup.boolSetting", scope=SettingsScope.SettingsUserScope)[0] == False, "test_settings_types failed" - assert settings.get_double_with_scope("testGroup.doubleSetting", scope=SettingsScope.SettingsUserScope)[0] == 700, "test_settings_types failed" - assert settings.get_integer_with_scope("testGroup.integerSetting", scope=SettingsScope.SettingsUserScope)[0] == 700, "test_settings_types failed" - assert settings.get_string_with_scope("testGroup.stringSetting", scope=SettingsScope.SettingsUserScope)[0] == "value_user", "test_settings_types failed" - assert settings.get_string_list_with_scope("testGroup.stringListSetting", scope=SettingsScope.SettingsUserScope)[0] == ["value3", "value4"], "test_settings_types failed" + assert settings.get_bool_with_scope("testGroup.boolSetting", scope=SettingsScope.SettingsUserScope + )[0] == False, "test_settings_types failed" + assert settings.get_double_with_scope("testGroup.doubleSetting", scope=SettingsScope.SettingsUserScope + )[0] == 700, "test_settings_types failed" + assert settings.get_integer_with_scope("testGroup.integerSetting", scope=SettingsScope.SettingsUserScope + )[0] == 700, "test_settings_types failed" + assert settings.get_string_with_scope("testGroup.stringSetting", scope=SettingsScope.SettingsUserScope + )[0] == "value_user", "test_settings_types failed" + assert settings.get_string_list_with_scope( + "testGroup.stringListSetting", scope=SettingsScope.SettingsUserScope + )[0] == ["value3", "value4"], "test_settings_types failed" raw_view = BinaryView.new(b'0x55') - assert not settings.set_bool("testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsDefaultScope), "test_settings_types failed" - assert not settings.set_bool("testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsResourceScope), "test_settings_types failed" - assert not settings.set_bool("testGroup.ignoreResourceBoolSetting", False, raw_view, scope=SettingsScope.SettingsResourceScope), "test_settings_types failed" - assert settings.set_bool("testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsUserScope), "test_settings_types failed" + assert not settings.set_bool( + "testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsDefaultScope + ), "test_settings_types failed" + assert not settings.set_bool( + "testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsResourceScope + ), "test_settings_types failed" + assert not settings.set_bool( + "testGroup.ignoreResourceBoolSetting", False, raw_view, scope=SettingsScope.SettingsResourceScope + ), "test_settings_types failed" + assert settings.set_bool( + "testGroup.ignoreResourceBoolSetting", False, scope=SettingsScope.SettingsUserScope + ), "test_settings_types failed" assert not settings.set_bool("testGroup.ignoreUserBoolSetting", False), "test_settings_types failed" assert settings.set_bool("testGroup.ignoreUserBoolSetting", False, raw_view), "test_settings_types failed" - assert settings.set_bool("testGroup.ignoreUserBoolSetting", False, raw_view, scope=SettingsScope.SettingsResourceScope), "test_settings_types failed" + assert settings.set_bool( + "testGroup.ignoreUserBoolSetting", False, raw_view, scope=SettingsScope.SettingsResourceScope + ), "test_settings_types failed" assert not settings.set_bool("testGroup.readOnlyBoolSetting", False), "test_settings_types failed" - assert not settings.set_bool("testGroup.readOnlyBoolSetting", False, scope=SettingsScope.SettingsResourceScope), "test_settings_types failed" - assert not settings.set_bool("testGroup.readOnlyBoolSetting", False, scope=SettingsScope.SettingsUserScope), "test_settings_types failed" + assert not settings.set_bool( + "testGroup.readOnlyBoolSetting", False, scope=SettingsScope.SettingsResourceScope + ), "test_settings_types failed" + assert not settings.set_bool( + "testGroup.readOnlyBoolSetting", False, scope=SettingsScope.SettingsUserScope + ), "test_settings_types failed" s2 = Settings("test2") assert s2.serialize_schema() == "", "test_settings_types failed" @@ -156,12 +247,16 @@ class SettingsAPI(unittest.TestCase): assert s2.get_string("testGroup.stringSetting") == "value", "test_settings_types failed" assert s2.get_string_list("testGroup.stringListSetting") == ["value1", "value2"], "test_settings_types failed" - assert s2.deserialize_settings(settings.serialize_settings(scope = SettingsScope.SettingsUserScope), raw_view, SettingsScope.SettingsResourceScope), "test_settings_types failed" + assert s2.deserialize_settings( + settings.serialize_settings(scope=SettingsScope.SettingsUserScope), raw_view, + SettingsScope.SettingsResourceScope + ), "test_settings_types failed" assert s2.get_bool("testGroup.boolSetting", raw_view) == False, "test_settings_types failed" assert s2.get_double("testGroup.doubleSetting", raw_view) == 700, "test_settings_types failed" assert s2.get_integer("testGroup.integerSetting", raw_view) == 700, "test_settings_types failed" assert s2.get_string("testGroup.stringSetting", raw_view) == "value_user", "test_settings_types failed" - assert s2.get_string_list("testGroup.stringListSetting", raw_view) == ["value3", "value4"], "test_settings_types failed" + assert s2.get_string_list("testGroup.stringListSetting", + raw_view) == ["value3", "value4"], "test_settings_types failed" assert s2.reset_all(), "test_settings_types failed" assert s2.get_bool("testGroup.boolSetting") == True, "test_settings_types failed" @@ -188,7 +283,9 @@ class SettingsAPI(unittest.TestCase): assert not s3.contains("testGroup.readOnlyBoolSetting"), "test_settings_types failed" def test_load_settings(self): - bvt_name = "Mapped (Python)" if "Mapped (Python)" in map(lambda bvt: bvt.name, list(BinaryViewType)) else "Mapped" + bvt_name = "Mapped (Python)" if "Mapped (Python)" in map( + lambda bvt: bvt.name, list(BinaryViewType) + ) else "Mapped" raw_view = BinaryView.new(b'0x55') assert raw_view.view_type == "Raw", "test_load_settings failed" mapped_view = BinaryViewType[bvt_name].create(raw_view) @@ -240,11 +337,9 @@ class MetaddataAPI(unittest.TestCase): assert len(md) == 4 assert md.value == "asdf" - md = Metadata("\x00\x00\x41\x00", raw=True) - assert md.is_raw + md = Metadata(b"\x00\x00\x41\x00") assert len(md) == 4 - assert str(md) == "\x00\x00\x41\x00" - assert md.value.decode("charmap") == "\x00\x00\x41\x00" + assert bytes(md) == b"\x00\x00\x41\x00" def test_metadata_compound_types(self): md = Metadata([1, 2, 3]) @@ -285,10 +380,10 @@ class MetaddataAPI(unittest.TestCase): assert Metadata("asdf") != "qwer" assert Metadata("asdf") != Metadata("qwer") - assert Metadata("as\x00df", raw=True) == "as\x00df" - assert Metadata("as\x00df", raw=True) == Metadata("as\x00df", raw=True) - assert Metadata("as\x00df", raw=True) != "qw\x00er" - assert Metadata("as\x00df", raw=True) != Metadata("qw\x00er", raw=True) + assert Metadata(b"as\x00df") == b"as\x00df" + assert Metadata(b"as\x00df") == Metadata(b"as\x00df") + assert Metadata(b"as\x00df") != b"qw\x00er" + assert Metadata(b"as\x00df") != Metadata(b"qw\x00er") assert Metadata([1, 2, 3]) == [1, 2, 3] assert Metadata([1, 2, 3]) == Metadata([1, 2, 3]) @@ -313,60 +408,51 @@ class DemanglerTest(unittest.TestCase): return out def test_demangle_ms(self): - tests = ( - "??_V@YAPAXI@Z", - "??_U@YAPAXI@Z" - ) + tests = ("??_V@YAPAXI@Z", "??_U@YAPAXI@Z") - oracle = ( - "void* __cdecl operator delete[](uint32_t)", - "void* __cdecl operator new[](uint32_t)" - ) + oracle = ("void* __cdecl operator delete[](uint32_t)", "void* __cdecl operator new[](uint32_t)") for i, test in enumerate(tests): t, n = demangle_ms(Architecture['x86'], test) result = self.get_type_string(t, n) assert result == oracle[i], f"oracle: {oracle[i]}\nresult: {result}" def test_demangle_gnu3(self): - tests = ("__ZN15BinaryNinjaCore12BinaryReader5Read8Ev", - "__ZN5QListIP18QAbstractAnimationE18detach_helper_growEii", - "__ZN13QStatePrivate22emitPropertiesAssignedEv", - "__ZN17QtMetaTypePrivate23QMetaTypeFunctionHelperI14QItemSelectionLb1EE9ConstructEPvPKv", - "__ZN18QSharedDataPointerI16QFileInfoPrivateE4dataEv", - "__ZN26QAbstractNativeEventFilterD2Ev", - "__ZN5QListIP14QAbstractStateE3endEv", - "__ZNK15BinaryNinjaCore19ArchitectureWrapper22GetOpcodeDisplayLengthEv", - "__ZN15BinaryNinjaCore17ScriptingInstance19SetCurrentSelectionEyy", - "__ZN12_GLOBAL__N_114TypeDestructor14DestructorImplI11QStringListLb1EE8DestructEiPv", - "__ZN13QGb18030Codec5_nameEv", - "__ZN5QListIP7QObjectE6detachEv", - "__ZN19QBasicAtomicPointerI9QFreeListI13QMutexPrivateN12_GLOBAL__N_117FreeListConstantsEEE17testAndSetReleaseEPS4_S6_", - "__ZN12QJsonPrivate6Parser12reserveSpaceEi", - "__ZN20QStateMachinePrivate12endMacrostepEb", - "__ZN14QScopedPointerI20QTemporaryDirPrivate21QScopedPointerDeleterIS0_EED2Ev", - "__ZN14QVariantIsNullIN12_GLOBAL__N_115CoreTypesFilterEE8delegateI10QMatrix4x4EEbPKT_", - "__ZN26QAbstractProxyModelPrivateC2Ev", - "__ZNSt3__110__function6__funcIZ26BNWorkerInteractiveEnqueueE4$_16NS_9allocatorIS2_EEFvvEEclEv") + tests = ( + "__ZN15BinaryNinjaCore12BinaryReader5Read8Ev", "__ZN5QListIP18QAbstractAnimationE18detach_helper_growEii", + "__ZN13QStatePrivate22emitPropertiesAssignedEv", + "__ZN17QtMetaTypePrivate23QMetaTypeFunctionHelperI14QItemSelectionLb1EE9ConstructEPvPKv", + "__ZN18QSharedDataPointerI16QFileInfoPrivateE4dataEv", "__ZN26QAbstractNativeEventFilterD2Ev", + "__ZN5QListIP14QAbstractStateE3endEv", + "__ZNK15BinaryNinjaCore19ArchitectureWrapper22GetOpcodeDisplayLengthEv", + "__ZN15BinaryNinjaCore17ScriptingInstance19SetCurrentSelectionEyy", + "__ZN12_GLOBAL__N_114TypeDestructor14DestructorImplI11QStringListLb1EE8DestructEiPv", + "__ZN13QGb18030Codec5_nameEv", "__ZN5QListIP7QObjectE6detachEv", + "__ZN19QBasicAtomicPointerI9QFreeListI13QMutexPrivateN12_GLOBAL__N_117FreeListConstantsEEE17testAndSetReleaseEPS4_S6_", + "__ZN12QJsonPrivate6Parser12reserveSpaceEi", "__ZN20QStateMachinePrivate12endMacrostepEb", + "__ZN14QScopedPointerI20QTemporaryDirPrivate21QScopedPointerDeleterIS0_EED2Ev", + "__ZN14QVariantIsNullIN12_GLOBAL__N_115CoreTypesFilterEE8delegateI10QMatrix4x4EEbPKT_", + "__ZN26QAbstractProxyModelPrivateC2Ev", + "__ZNSt3__110__function6__funcIZ26BNWorkerInteractiveEnqueueE4$_16NS_9allocatorIS2_EEFvvEEclEv" + ) - oracle = ("int32_t BinaryNinjaCore::BinaryReader::Read8()", - "int32_t QList<QAbstractAnimation*>::detach_helper_grow(int32_t, int32_t)", - "int32_t QStatePrivate::emitPropertiesAssigned()", - "int32_t QtMetaTypePrivate::QMetaTypeFunctionHelper<QItemSelection, true>::Construct(void*, void const*)", - "int32_t QSharedDataPointer<QFileInfoPrivate>::data()", - "void QAbstractNativeEventFilter::~QAbstractNativeEventFilter()", - "int32_t QList<QAbstractState*>::end()", - "int32_t BinaryNinjaCore::ArchitectureWrapper::GetOpcodeDisplayLength() const", - "int32_t BinaryNinjaCore::ScriptingInstance::SetCurrentSelection(uint64_t, uint64_t)", - "int32_t (anonymous namespace)::TypeDestructor::DestructorImpl<QStringList, true>::Destruct(int32_t, void*)", - "int32_t QGb18030Codec::_name()", - "int32_t QList<QObject*>::detach()", - "int32_t QBasicAtomicPointer<QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants> >::testAndSetRelease(QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants>*, QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants>*)", - "int32_t QJsonPrivate::Parser::reserveSpace(int32_t)", - "int32_t QStateMachinePrivate::endMacrostep(bool)", - "void QScopedPointer<QTemporaryDirPrivate, QScopedPointerDeleter<QTemporaryDirPrivate> >::~QScopedPointer()", - "bool QVariantIsNull<(anonymous namespace)::CoreTypesFilter>::delegate<QMatrix4x4>(QMatrix4x4 const*)", - "void QAbstractProxyModelPrivate::QAbstractProxyModelPrivate()", - "int32_t std::__1::__function::__func<BNWorkerInteractiveEnqueue::$_16, std::__1::allocator<BNWorkerInteractiveEnqueue::$_16>, void ()>::operator()()") + oracle = ( + "int32_t BinaryNinjaCore::BinaryReader::Read8()", + "int32_t QList<QAbstractAnimation*>::detach_helper_grow(int32_t, int32_t)", + "int32_t QStatePrivate::emitPropertiesAssigned()", + "int32_t QtMetaTypePrivate::QMetaTypeFunctionHelper<QItemSelection, true>::Construct(void*, void const*)", + "int32_t QSharedDataPointer<QFileInfoPrivate>::data()", + "void QAbstractNativeEventFilter::~QAbstractNativeEventFilter()", "int32_t QList<QAbstractState*>::end()", + "int32_t BinaryNinjaCore::ArchitectureWrapper::GetOpcodeDisplayLength() const", + "int32_t BinaryNinjaCore::ScriptingInstance::SetCurrentSelection(uint64_t, uint64_t)", + "int32_t (anonymous namespace)::TypeDestructor::DestructorImpl<QStringList, true>::Destruct(int32_t, void*)", + "int32_t QGb18030Codec::_name()", "int32_t QList<QObject*>::detach()", + "int32_t QBasicAtomicPointer<QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants> >::testAndSetRelease(QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants>*, QFreeList<QMutexPrivate, (anonymous namespace)::FreeListConstants>*)", + "int32_t QJsonPrivate::Parser::reserveSpace(int32_t)", "int32_t QStateMachinePrivate::endMacrostep(bool)", + "void QScopedPointer<QTemporaryDirPrivate, QScopedPointerDeleter<QTemporaryDirPrivate> >::~QScopedPointer()", + "bool QVariantIsNull<(anonymous namespace)::CoreTypesFilter>::delegate<QMatrix4x4>(QMatrix4x4 const*)", + "void QAbstractProxyModelPrivate::QAbstractProxyModelPrivate()", + "int32_t std::__1::__function::__func<BNWorkerInteractiveEnqueue::$_16, std::__1::allocator<BNWorkerInteractiveEnqueue::$_16>, void ()>::operator()()" + ) for i, test in enumerate(tests): t, n = demangle_gnu3(Architecture['x86'], test) @@ -404,31 +490,16 @@ class TypeParserTest(unittest.TestCase): self.p = Platform[self.arch] def test_integers(self): - integers = [ - ("a", "char a;", 1, True), - ("b", "unsigned char b;", 1, False), - ("c", "signed char c;", 1, True), - ("d", "int8_t d;", 1, True), - ("e", "uint8_t e;", 1, False), - ("f", "short f;", 2, True), - ("g", "unsigned short g;", 2, False), - ("h", "signed short h;", 2, True), - ("i", "short int i;", 2, True), - ("j", "unsigned short int j;", 2, False), - ("k", "signed short int k;", 2, True), - ("l", "uint16_t l;", 2, False), - ("m", "int16_t m;", 2, True), - ("n", "int n;", 4, True), - ("o", "unsigned int o;", 4, False), - ("p", "signed int p;", 4, True), - ("t", "int32_t t;", 4, True), - ("u", "uint32_t u;", 4, False), - ("q", "long int q;", 8, True), - ("r", "unsigned long int r;", 8, False), - ("s", "signed long int s;", 8, True), - ("v", "long long v;", 8, True), - ("w", "long long int w;", 8, True), - ("x", "unsigned long long int x;", 8, False)] + integers = [("a", "char a;", 1, True), ("b", "unsigned char b;", 1, False), ("c", "signed char c;", 1, True), + ("d", "int8_t d;", 1, True), ("e", "uint8_t e;", 1, False), ("f", "short f;", 2, True), + ("g", "unsigned short g;", 2, False), ("h", "signed short h;", 2, True), + ("i", "short int i;", 2, True), ("j", "unsigned short int j;", 2, False), + ("k", "signed short int k;", 2, True), ("l", "uint16_t l;", 2, False), ("m", "int16_t m;", 2, True), + ("n", "int n;", 4, True), ("o", "unsigned int o;", 4, False), ("p", "signed int p;", 4, True), + ("t", "int32_t t;", 4, True), ("u", "uint32_t u;", 4, False), ("q", "long int q;", 8, True), + ("r", "unsigned long int r;", 8, False), ("s", "signed long int s;", 8, True), + ("v", "long long v;", 8, True), ("w", "long long int w;", 8, True), + ("x", "unsigned long long int x;", 8, False)] for name, definition, size, signed in integers: with self.subTest(): @@ -438,91 +509,72 @@ class TypeParserTest(unittest.TestCase): assert signed == var.signed, f"Sign for type: {definition} isn't {'signed' if signed else 'unsigned'}" def test_structures(self): - structures = [ - ("a", "struct a { uint32_t x; uint64_t y; };", 16, 8, 2), - ("b", "struct b { uint64_t x; uint64_t y; };", 16, 8, 2), - ("c", "struct c { uint64_t x; uint32_t y; };", 16, 8, 2), - ] + structures = [("a", "struct a { uint32_t x; uint64_t y; };", 16, 8, 2), + ("b", "struct b { uint64_t x; uint64_t y; };", 16, 8, 2), + ("c", "struct c { uint64_t x; uint32_t y; };", 16, 8, 2), ] for name, definition, size, alignment, members in structures: with self.subTest(): result = self.p.parse_types_from_source(definition) s = result.types[name] - assert len(s) == size, f"Structure property: 'size' {size} incorrect for {definition} got {len(s)} instead" + 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" + assert len( + s.members + ) == members, f"Structure property: 'members' {members} incorrect for {definition} got {len(s.members)} instead" def test_alignment_packing(self): - structures = [ - ("a", "struct a { uint64_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - - ("a", "struct a { uint64_t a; uint64_t b; uint32_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint32_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint32_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), - - ("a", "struct a { uint64_t a; uint64_t b; uint16_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint32_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xc)), - ("a", "struct a { uint64_t a; uint16_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint16_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), - ("a", "struct a { uint64_t a; uint16_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xa)), - - ("a", "struct a { uint64_t a; uint64_t b; uint8_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint32_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0xc)), - ("a", "struct a { uint64_t a; uint16_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0xa)), - ("a", "struct a { uint64_t a; uint8_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint64_t a; uint8_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), - ("a", "struct a { uint64_t a; uint8_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xa)), - ("a", "struct a { uint64_t a; uint8_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0x9)), - - ("a", "struct a { uint32_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint32_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), - ("a", "struct a { uint32_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), - ("a", "struct a { uint32_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), - - ("a", "struct a { uint16_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint16_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), - ("a", "struct a { uint16_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), - ("a", "struct a { uint16_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), - - ("a", "struct a { uint8_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), - ("a", "struct a { uint8_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), - ("a", "struct a { uint8_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), - ("a", "struct a { uint8_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x1, 0x8)), - - ("a", "struct a { uint8_t a; struct { uint64_t c; } b; };", 0x10, (0x0, 0x8)), - ("a", "struct a { uint8_t a; struct { uint32_t c; } b; };", 0x8, (0x0, 0x4)), - ("a", "struct a { uint8_t a; struct { uint16_t c; } b; };", 0x4, (0x0, 0x2)), - ("a", "struct a { uint8_t a; struct { uint16_t c; uint16_t d; } b; };", 0x6, (0x0, 0x2)), - ("a", "struct a { uint8_t a; struct { uint8_t c; uint16_t d; } b; };", 0x6, (0x0, 0x2)), - ("a", "struct a { uint8_t a; struct { uint8_t c; uint8_t d; } b; };", 0x3, (0x0, 0x1)), - ] + structures = [("a", "struct a { uint64_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint64_t b; uint32_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint32_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint32_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), + ("a", "struct a { uint64_t a; uint64_t b; uint16_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint32_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xc)), + ("a", "struct a { uint64_t a; uint16_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint16_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), + ("a", "struct a { uint64_t a; uint16_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xa)), + ("a", "struct a { uint64_t a; uint64_t b; uint8_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint32_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0xc)), + ("a", "struct a { uint64_t a; uint16_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0xa)), + ("a", "struct a { uint64_t a; uint8_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint64_t a; uint8_t b; uint32_t c; };", 0x10, (0x0, 0x8, 0xc)), + ("a", "struct a { uint64_t a; uint8_t b; uint16_t c; };", 0x10, (0x0, 0x8, 0xa)), + ("a", "struct a { uint64_t a; uint8_t b; uint8_t c; };", 0x10, (0x0, 0x8, 0x9)), + ("a", "struct a { uint32_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint32_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), + ("a", "struct a { uint32_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), + ("a", "struct a { uint32_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), + ("a", "struct a { uint16_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint16_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), + ("a", "struct a { uint16_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), + ("a", "struct a { uint16_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), + ("a", "struct a { uint8_t a; uint64_t b; uint64_t c; };", 0x18, (0x0, 0x8, 0x10)), + ("a", "struct a { uint8_t a; uint32_t b; uint64_t c; };", 0x10, (0x0, 0x4, 0x8)), + ("a", "struct a { uint8_t a; uint16_t b; uint64_t c; };", 0x10, (0x0, 0x2, 0x8)), + ("a", "struct a { uint8_t a; uint8_t b; uint64_t c; };", 0x10, (0x0, 0x1, 0x8)), + ("a", "struct a { uint8_t a; struct { uint64_t c; } b; };", 0x10, (0x0, 0x8)), + ("a", "struct a { uint8_t a; struct { uint32_t c; } b; };", 0x8, (0x0, 0x4)), + ("a", "struct a { uint8_t a; struct { uint16_t c; } b; };", 0x4, (0x0, 0x2)), + ("a", "struct a { uint8_t a; struct { uint16_t c; uint16_t d; } b; };", 0x6, (0x0, 0x2)), + ("a", "struct a { uint8_t a; struct { uint8_t c; uint16_t d; } b; };", 0x6, (0x0, 0x2)), + ("a", "struct a { uint8_t a; struct { uint8_t c; uint8_t d; } b; };", 0x3, (0x0, 0x1)), ] for name, definition, size, member_offsets in structures: with self.subTest(): result = self.p.parse_types_from_source(definition) s = result.types[name] - assert len(s) == size, f"Structure property: 'size' {size} incorrect for {definition} got {len(s)} instead" + assert len( + s + ) == size, f"Structure property: 'size' {size} incorrect for {definition} got {len(s)} instead" for expect_offset, member in zip(member_offsets, s.members): assert member.offset == expect_offset, f"Structure member property: 'offset' {expect_offset} incorrect for {member.name} in {definition} got {member.offset} instead" def test_escaping(self): - escaped = [ - ('test', 'test', 'test'), - ('a0b', 'a0b', 'a0b'), - ('a$b', 'a$b', 'a$b'), - ('a_b', 'a_b', 'a_b'), - ('a@b', 'a@b', 'a@b'), - ('a!b', 'a!b', 'a!b'), - ('0a', '0a', '`0a`'), - ('_a', '_a', '_a'), - ('$a', '$a', '$a'), - ('@a', '@a', '`@a`'), - ('!a', '!a', '`!a`'), - ('a::b', 'a::b', '`a::b`'), - ('a b', 'a b', '`a b`'), - ('a`b', 'a`b', '`a\\`b`'), - ('a\\b', 'a\\b', '`a\\\\b`'), - ('a\\`b', 'a\\`b', '`a\\\\\\`b`'), - ('a\\\\`b', 'a\\\\`b', '`a\\\\\\\\\\`b`'), - ] + escaped = [('test', 'test', 'test'), ('a0b', 'a0b', 'a0b'), ('a$b', 'a$b', 'a$b'), ('a_b', 'a_b', 'a_b'), + ('a@b', 'a@b', 'a@b'), ('a!b', 'a!b', 'a!b'), ('0a', '0a', '`0a`'), ('_a', '_a', '_a'), + ('$a', '$a', '$a'), ('@a', '@a', '`@a`'), ('!a', '!a', '`!a`'), ('a::b', 'a::b', '`a::b`'), + ('a b', 'a b', '`a b`'), ('a`b', 'a`b', '`a\\`b`'), ('a\\b', 'a\\b', '`a\\\\b`'), + ('a\\`b', 'a\\`b', '`a\\\\\\`b`'), ('a\\\\`b', 'a\\\\`b', '`a\\\\\\\\\\`b`'), ] for source, expect_none, expect_backticks in escaped: got_none = QualifiedName.escape(source, TokenEscapingType.NoTokenEscapingType) assert got_none == expect_none, f"Escape test of {source} NoTokenEscapingType got {got_none} expected {expect_none}" @@ -550,7 +602,9 @@ class TypeParserTest(unittest.TestCase): ''' types = self.p.parse_types_from_source(valid) assert types.types['type name with space'] == Type.int(4, False) - assert types.types['another name'].name == QualifiedName(['type name with space']), f"Expected typedef, got {types.types['another name']}" + assert types.types['another name'].name == QualifiedName( + ['type name with space'] + ), f"Expected typedef, got {types.types['another name']}" assert len(types.types['space enum'].members) == 2 assert len(types.types['space struct'].members) == 3 assert types.types['space struct'].members[0].name == 'first member' @@ -845,7 +899,7 @@ class TypeTest(unittest.TestCase): assert b[1].name == "Member10" assert b[1].value == 10 assert b["Member_doesn't exist"] == None - self.assertRaises(ValueError, lambda : b.__setitem__(None, None)) + self.assertRaises(ValueError, lambda: b.__setitem__(None, None)) e1 = EnumerationMember("Member10", 10) assert e1.value == 10 @@ -1010,8 +1064,10 @@ class TypeTest(unittest.TestCase): t = Type.structure([Type.int(4)]) assert t.mutable_copy().immutable_copy() == t t1 = t - t = Type.structure([StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), - StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope)]) + t = Type.structure([ + StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), + StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope) + ]) t2 = t self.assertRaises(ValueError, lambda: Type.structure([None])) assert hash(t1) != hash(t2) @@ -1026,18 +1082,24 @@ class TypeTest(unittest.TestCase): self.assertRaises(ValueError, lambda: t.member_at_offset(-1)) assert not t.packed - t = Type.union([StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), - StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope)]) + t = Type.union([ + StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), + StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope) + ]) ntr = t.generate_named_type_reference("guid", "name") assert ntr.name == "name" - t = Type.class_type([StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), - StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope)]) + t = Type.class_type([ + StructureMember(Type.int(4), "first", 0, MemberAccess.PublicAccess, MemberScope.StaticScope), + StructureMember(Type.int(4), "second", 4, MemberAccess.PublicAccess, MemberScope.StaticScope) + ]) ntr = t.generate_named_type_reference("guid", "name") assert ntr.name == "name" def test_NamedTypeReferenceType(self): - t = Type.named_type(NamedTypeReferenceBuilder.create(NamedTypeReferenceClass.UnknownNamedTypeClass, "id", "name")) + t = Type.named_type( + NamedTypeReferenceBuilder.create(NamedTypeReferenceClass.UnknownNamedTypeClass, "id", "name") + ) assert t.mutable_copy().immutable_copy() == t t = Type.named_type_from_type_and_id("id2", ["qualified", "name"]) assert t.mutable_copy().immutable_copy() == t @@ -1069,13 +1131,11 @@ class TypeTest(unittest.TestCase): assert b.named_type_class == NamedTypeReferenceClass.UnionNamedTypeClass assert repr(b).startswith("<type: immutable:NamedTypeReferenceClass 'union") - b = NamedTypeReferenceType.generate_auto_type_ref(NamedTypeReferenceClass.UnionNamedTypeClass, - "foo", "bar") + b = NamedTypeReferenceType.generate_auto_type_ref(NamedTypeReferenceClass.UnionNamedTypeClass, "foo", "bar") assert b.type_id.startswith("foo") assert b.name == "bar" assert b.named_type_class == NamedTypeReferenceClass.UnionNamedTypeClass - b = NamedTypeReferenceType.generate_auto_demangled_type_ref(NamedTypeReferenceClass.UnionNamedTypeClass, - "bar") + b = NamedTypeReferenceType.generate_auto_demangled_type_ref(NamedTypeReferenceClass.UnionNamedTypeClass, "bar") assert b.type_id.startswith("demange") def test_EnumerationType(self): @@ -1159,8 +1219,10 @@ class TestSymbols(unittest.TestCase): assert sym.raw_bytes == b"_Jv_RegisterClasses" assert sym.ordinal == 0 assert sym.auto - sym = Symbol("DataSymbol", 0, "short_name", "full_name", "raw_name", SymbolBinding.GlobalBinding, - NameSpace("BN_INTERNAL_NAMESPACE"), 2) + sym = Symbol( + "DataSymbol", 0, "short_name", "full_name", "raw_name", SymbolBinding.GlobalBinding, + NameSpace("BN_INTERNAL_NAMESPACE"), 2 + ) assert sym.binding == SymbolBinding.GlobalBinding assert sym.short_name == "short_name" assert sym.full_name == "full_name" @@ -1174,11 +1236,7 @@ class TestSymbols(unittest.TestCase): assert str(ns) == str(NameSpace._from_core_struct(ns._to_core_struct())) -class TestTypesWithBinaryView(unittest.TestCase): - def setUp(self): - self.apparatus = Apparatus("helloworld") - self.bv = self.apparatus.bv - +class TestTypes(TestWithBinaryView): def test_named_type_from_registered_type(self): n = Type.named_type_from_registered_type(self.bv, "Elf32_Dyn") assert n.name == "Elf32_Dyn" @@ -1198,15 +1256,13 @@ class TestTypesWithBinaryView(unittest.TestCase): s = self.bv.types["Elf32_Dyn"] n = s.registered_name assert s == n.target(self.bv) - unregistered_ntr = NamedTypeReferenceType.generate_auto_demangled_type_ref(NamedTypeReferenceClass.EnumNamedTypeClass, "foobar") + unregistered_ntr = NamedTypeReferenceType.generate_auto_demangled_type_ref( + NamedTypeReferenceClass.EnumNamedTypeClass, "foobar" + ) assert unregistered_ntr.target(self.bv) == None -class TestMutableTypeBuilder(unittest.TestCase): - def setUp(self): - self.apparatus = Apparatus("helloworld") - self.bv = self.apparatus.bv - +class TestMutableTypeBuilder(TestWithBinaryView): def test_MutableTypeBuilder(self): with Type.builder(self.bv, "Elf32_Dyn") as b: assert isinstance(b, StructureBuilder) @@ -1231,3 +1287,231 @@ class TestMutableTypeBuilder(unittest.TestCase): with MutableTypeBuilder(self.bv.types["Elf32_Dyn"].mutable_copy(), self.bv, "Elf32_Dyn", None, 255, False) as b: b.append(Type.int(4), "test_field2") + + +class TestWithFunction(TestWithBinaryView): + def setUp(self): + super().setUp() + self.func = self.bv.get_functions_by_name("main")[0] + + def test_equality(self): + func1 = self.func + func2 = self.bv.get_function_at(0x0000848c) + assert func1 == func1 + assert func1 != func2 + assert func1.start < 0x0000848c + assert func1 < func2 + assert func1 <= func2 + assert func2 > func1 + assert func2 >= func1 + + def test_getters(self): + assert isinstance(self.func[0], BasicBlock) + it = iter(self.func) + assert isinstance(next(it), BasicBlock) + assert next(it) in self.func + assert self.func.start in self.func + + def test_name_symbol(self): + assert self.func.name == "main" + my_name = "my_name" + my_name2 = "my_name" + self.func.name = my_name + assert self.func.name == my_name + self.func.name = Symbol(SymbolType.FunctionSymbol, self.func.start, my_name2) + assert self.func.name == my_name2 + self.func.name = None + assert self.func.name == "main" + + sym = self.func.symbol + assert sym.type == SymbolType.FunctionSymbol + assert sym.address == self.func.start + assert sym.name == self.func.name + + def test_view_arch_platform(self): + assert isinstance(self.bv, BinaryView) + assert isinstance(self.arch, Architecture) + assert isinstance(self.plat, Platform) + + def test_size_and_addresses(self): + assert self.func.total_bytes == 68 + assert self.func.lowest_address == 0x8440 + assert self.func.highest_address == 0x8483 + assert len(self.func.address_ranges) == 1 + assert self.func.address_ranges[0].start == 0x8440 + assert self.func.address_ranges[0].end == 0x8484 + + def test_auto(self): + assert not self.func.auto + assert not self.func.has_user_annotations + # cause a user annotation + self.func.parameter_vars[0].name = "arg_count" + assert self.func.has_user_annotations + + def test_no_return(self): + assert self.func.can_return + self.func.can_return = False + self.bv.update_analysis_and_wait() + assert not self.func.can_return + self.func.can_return = True + self.bv.update_analysis_and_wait() + assert self.func.can_return + + def test_explicitly_defined_types(self): + assert self.func.explicitly_defined_type + func2 = self.bv.get_function_at(0x0000840c) + assert not func2.explicitly_defined_type + + def test_needs_update(self): + assert not self.func.needs_update + + def test_comments(self): + assert self.func.comments == {} + self.func.set_comment(0x00008470, "my_comment") + assert self.func.comments == {0x00008470: 'my_comment'} + self.func.comment = "Function Level Comment" + assert self.func.comment == "Function Level Comment" + + def test_create_tag(self): + msg1 = "Bugs here" + msg2 = "Crashes here" + msg3 = "Library here" + msg4 = "Important here" + name1 = "Bugs" + name2 = "Crashes" + name3 = "Library" + name4 = "Important" + tt1 = self.bv.tag_types[name1] + tt2 = self.bv.tag_types[name2] + tt3 = self.bv.tag_types[name3] + tt4 = self.bv.tag_types[name4] + tag1 = self.func.create_tag(tt1, msg1, True) + tag2 = self.func.create_user_tag(tt2, msg2) + tag3 = self.func.create_auto_tag(tt3, msg3) + tag4 = self.func.create_auto_tag(tt4, msg4) + + assert len(self.func.function_tags) == 0 + self.func.add_user_function_tag(tag1) + self.func.add_user_function_tag(tag2) + self.func.add_user_function_tag(tag3) + t = self.func.create_user_function_tag(tt4, msg4, True) + t = self.func.create_user_function_tag(tt4, msg4, True) + tags = self.func.function_tags + assert len(tags) == 4 + assert tags[0].data == msg1 + assert tags[0].type == tt1 + assert tags[1].data == msg2 + assert tags[1].type == tt2 + assert tags[2].data == msg3 + assert tags[2].type == tt3 + assert tags[3].data == msg4 + assert tags[3].type == tt4 + assert tags[3] == t + self.func.remove_user_function_tag(tags[0]) + self.func.remove_user_function_tag(tags[1]) + self.func.remove_user_function_tag(tags[2]) + self.func.remove_user_function_tag(tags[3]) + assert len(self.func.function_tags) == 0 + + addr = self.func.start + 4 + + assert len(self.func.address_tags) == 0 + self.func.add_user_address_tag(addr, tag1) + tags = self.func.address_tags + assert len(tags) == 1 + _, addr, tag = tags[0] + assert addr == addr + assert tag.data == msg1 + assert tag.type == tt1 + self.func.remove_user_address_tag(addr, tag) + assert len(self.func.address_tags) == 0 + + self.assertRaises(TypeError, lambda: self.func.create_user_address_tag(0, None, None)) + + t = self.func.create_user_address_tag(addr, tt1, msg1, True) + t = self.func.create_user_address_tag(addr, tt1, msg1, True) + tags = self.func.address_tags + assert len(tags) == 1 + _, addr, tag = tags[0] + assert t == tag + assert tag.data == msg1 + assert tag.type == tt1 + self.func.remove_user_address_tag(addr, tag) + assert len(self.func.address_tags) == 0 + + assert len(self.func.function_tags) == 0 + self.func.add_auto_function_tag(tag1) + t = self.func.create_auto_function_tag(tt2, msg2, True) + t = self.func.create_auto_function_tag(tt2, msg2, True) + tags = self.func.function_tags + assert len(tags) == 2 + assert tags[0].data == msg1 + assert tags[0].type == tt1 + assert tags[1].data == msg2 + assert tags[1].type == tt2 + assert tags[1] == t + self.func.remove_auto_function_tag(tags[0]) + self.func.remove_auto_function_tag(tags[1]) + assert len(self.func.function_tags) == 0 + + assert len(self.func.address_tags) == 0 + self.func.add_auto_address_tag(addr, tag1, self.func.arch) + t = self.func.create_auto_address_tag(addr, tt2, msg2, True) + t = self.func.create_auto_address_tag(addr, tt2, msg2, True) + tags = self.func.address_tags + assert len(tags) == 2 + assert t == tags[1][2] + assert tags[0][2].data == msg1 + assert tags[0][2].type == tt1 + assert tags[1][2].data == msg2 + assert tags[1][2].type == tt2 + self.func.remove_auto_address_tag(addr, tags[0][2]) + self.func.remove_auto_address_tag(addr, tags[1][2]) + assert len(self.func.address_tags) == 0 + + +class TestBinaryView(TestWithBinaryView): + def test_TagType(self): + tt = self.bv.tag_types["Crashes"] + t2 = self.bv.tag_types["Bugs"] + assert repr(tt).startswith("<tag type Crashes: 🛑>") + assert tt == tt + assert tt != t2 + assert not (tt == t2) + assert not (tt != tt) + assert tt.__eq__(None) == NotImplemented + assert tt.__ne__(None) == NotImplemented + assert hash(tt) != hash(t2) + assert len(tt.id) == len('796636ee-f2c3-4f67-a15e-20571fe37db2') + assert tt.name == "Crashes" + tt.name = "More Crashes" + assert tt.name == "More Crashes" + assert tt.icon == '🛑' + tt.icon = '👀' + assert tt.icon == '👀' + assert tt.visible + tt.visible = False + assert not tt.visible + assert tt.type == TagTypeType.UserTagType + tt.type = TagTypeType.NotificationTagType + assert tt.type == TagTypeType.NotificationTagType + tt.type = TagTypeType.UserTagType + assert tt.type == TagTypeType.UserTagType + + def test_Tag(self): + func = self.bv.get_function_at(0x0000836c) + assert len(func.address_tags) == 1 + arch, addr, tag = func.address_tags[0] + assert repr(tag).startswith("<tag ") + assert arch == func.arch + assert addr == 0x00008390 + assert tag.data == 'Non-code call target 0x0' + assert tag.type == self.bv.tag_types['Non-code Branch'] + func = self.bv.get_function_at(0x000083a4) + assert len(func.address_tags) == 1 + _, _, other_tag = func.address_tags[0] + assert tag == tag + assert tag != other_tag + assert tag.__eq__(None) == NotImplemented + assert tag.__ne__(None) == NotImplemented + assert hash(tag) != hash(other_tag) |
