import unittest import platform import os from binaryninja.binaryview import BinaryView, BinaryViewType from binaryninja.settings import Settings, SettingsScope from binaryninja.metadata import Metadata 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.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.lowlevelil import * from binaryninja.mediumlevelil import * from binaryninja.highlevelil import * from binaryninja.variable import * 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__)) assert os.path.exists(self.path) self.bv = BinaryViewType.get_view_of_file(os.path.relpath(self.path)) @property def path(self) -> str: return os.path.join(os.path.dirname(__file__), self.test_store, self.filename) def __del__(self): if os.path.exists(self.path): os.unlink(self.path) self.bv.file.close() def __enter__(self): return self.bv def __exit__(self, type, value, traceback): 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): pass @classmethod def tearDownClass(cls): pass def test_settings_create(self): s1 = Settings() s2 = Settings(None) s3 = Settings("default") s4 = Settings("test") assert s1 == s2, "test_settings_create failed" assert s1 == s3, "test_settings_create failed" assert s1 != s4, "test_settings_create failed" def test_settings_defaults(self): settings = Settings() 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" 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.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 settings.contains("testGroup.boolSetting"), "test_settings_types failed" assert settings.contains("testGroup.doubleSetting"), "test_settings_types failed" assert settings.contains("testGroup.integerSetting"), "test_settings_types failed" assert settings.contains("testGroup.stringSetting"), "test_settings_types failed" assert settings.contains("testGroup.stringListSetting"), "test_settings_types failed" assert settings.get_bool("testGroup.boolSetting") == True, "test_settings_types failed" 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.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.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_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" 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.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 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" s2 = Settings("test2") assert s2.serialize_schema() == "", "test_settings_types failed" test_schema = settings.serialize_schema() assert test_schema != "", "test_settings_types failed" assert s2.deserialize_schema(test_schema), "test_settings_types failed" assert s2.get_bool("testGroup.boolSetting") == True, "test_settings_types failed" assert s2.get_double("testGroup.doubleSetting") == 500, "test_settings_types failed" assert s2.get_integer("testGroup.integerSetting") == 500, "test_settings_types failed" 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.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.reset_all(), "test_settings_types failed" assert s2.get_bool("testGroup.boolSetting") == True, "test_settings_types failed" assert s2.get_double("testGroup.doubleSetting") == 500, "test_settings_types failed" assert s2.get_integer("testGroup.integerSetting") == 500, "test_settings_types failed" assert s2.get_string("testGroup.stringSetting") == "value", "test_settings_types failed" assert s2.get_string_list("testGroup.stringListSetting") == ["value1", "value2"], "test_settings_types failed" s3 = Settings("test3") assert s3.deserialize_schema(test_schema, SettingsScope.SettingsResourceScope) assert not s3.contains("testGroup.ignoreResourceBoolSetting"), "test_settings_types failed" assert s3.contains("testGroup.ignoreUserBoolSetting"), "test_settings_types failed" assert not s3.contains("testGroup.readOnlyBoolSetting"), "test_settings_types failed" assert s3.deserialize_schema(test_schema, SettingsScope.SettingsUserScope, False) assert s3.contains("testGroup.ignoreResourceBoolSetting"), "test_settings_types failed" assert not s3.contains("testGroup.ignoreUserBoolSetting"), "test_settings_types failed" assert not s3.contains("testGroup.readOnlyBoolSetting"), "test_settings_types failed" assert s3.deserialize_schema(test_schema, SettingsScope.SettingsUserScope, False) assert s3.deserialize_schema(s3.serialize_schema(), SettingsScope.SettingsResourceScope, False) assert not s3.contains("testGroup.ignoreResourceBoolSetting"), "test_settings_types failed" assert not s3.contains("testGroup.ignoreUserBoolSetting"), "test_settings_types failed" 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" raw_view = BinaryView.new(b'0x55') assert raw_view.view_type == "Raw", "test_load_settings failed" mapped_view = BinaryViewType[bvt_name].create(raw_view) assert mapped_view.view_type == bvt_name, "test_load_settings failed" assert mapped_view.segments[0].start == 0, "test_load_settings failed" assert len(mapped_view) == 4, "test_load_settings failed" load_settings = BinaryViewType[bvt_name].get_load_settings_for_data(raw_view) assert load_settings is not None, "test_load_settings failed" assert load_settings.contains("loader.architecture"), "test_load_settings failed" assert load_settings.contains("loader.platform"), "test_load_settings failed" assert load_settings.contains("loader.imageBase"), "test_load_settings failed" assert load_settings.contains("loader.entryPointOffset"), "test_load_settings failed" load_settings.set_string("loader.architecture", 'x86_64') load_settings.set_integer("loader.imageBase", 0x500000) load_settings.set_integer("loader.entryPointOffset", 0) raw_view.set_load_settings(bvt_name, load_settings) mapped_view = BinaryViewType[bvt_name].create(raw_view) assert mapped_view.view_type == bvt_name, "test_load_settings failed" assert mapped_view.segments[0].start == 0x500000, "test_load_settings failed" assert len(mapped_view) == 4, "test_load_settings failed" assert raw_view.get_load_settings(bvt_name) == load_settings raw_view.set_load_settings(bvt_name, None) assert raw_view.get_load_settings(bvt_name) is None class MetaddataAPI(TestWithBinaryView): def test_metadata_basic_types(self): # Core is tested thoroughly through the C++ unit tests here we focus on the python api side md = Metadata(1) assert md.is_integer assert int(md) == 1 assert md.value == 1 md = Metadata(-1, signed=True) assert md.is_signed_integer assert int(md) == -1 assert md.value == -1 md = Metadata(1, signed=False) assert md.is_unsigned_integer assert int(md) == 1 md = Metadata(3.14) assert md.is_float assert float(md) == 3.14 assert md.value == 3.14 md = Metadata("asdf") assert md.is_string assert str(md) == "asdf" assert len(md) == 4 assert md.value == "asdf" md = Metadata(b"\x00\x00\x41\x00") assert len(md) == 4 assert bytes(md) == b"\x00\x00\x41\x00" def test_metadata_compound_types(self): md = Metadata([1, 2, 3]) assert md.is_array assert md.value == [1, 2, 3] assert len(md) == 3 assert md[0] == 1 assert md[1] == 2 assert md[2] == 3 assert isinstance(list(md), list) md.remove(0) assert len(md) == 2 assert md == [2, 3] md = Metadata({"a": 1, "b": 2}) assert md.is_dict assert len(md) == 2 assert md.value == {"a": 1, "b": 2} assert md["a"] == 1 assert md["b"] == 2 md.remove("a") assert len(md) == 1 assert md == {"b": 2} def test_metadata_equality(self): assert Metadata(1) == 1 assert Metadata(1) != 0 assert Metadata(1) == Metadata(1) assert Metadata(1) != Metadata(0) assert Metadata(3.14) == 3.14 assert Metadata(3.14) == Metadata(3.14) assert Metadata(3.14) != 3.1 assert Metadata(3.14) != Metadata(3.1) assert Metadata("asdf") == "asdf" assert Metadata("asdf") == Metadata("asdf") assert Metadata("asdf") != "qwer" assert Metadata("asdf") != Metadata("qwer") 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]) assert Metadata([1, 2, 3]) != [1, 2] assert Metadata([1, 2, 3]) != Metadata([1, 2]) assert Metadata({"a": 1, "b": 2}) == {"a": 1, "b": 2} assert Metadata({"a": 1, "b": 2}) == Metadata({"a": 1, "b": 2}) assert Metadata({"a": 1, "b": 2}) != {"a": 1} assert Metadata({"a": 1, "b": 2}) != Metadata({"a": 1}) def test_binaryview_storage(self): data = b"some bytes\x00\xff\xff\xff\xfe\xff\xcd\xcc" self.bv.store_metadata("SomeKey", data) assert self.bv.query_metadata("SomeKey") == data assert bytes(self.bv.query_metadata("SomeKey")) == data class DemanglerTest(unittest.TestCase): def get_type_string(self, t, n): out = "" if t is not None: out = str(t.get_string_before_name()) if len(out) > 1 and out[-1] != ' ': out += " " out += get_qualified_name(n) out += str(t.get_string_after_name()) return out def test_demangle_ms(self): tests = ("??_V@YAPAXI@Z", "??_U@YAPAXI@Z") 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" ) oracle = ( "int32_t BinaryNinjaCore::BinaryReader::Read8()", "int32_t QList::detach_helper_grow(int32_t, int32_t)", "int32_t QStatePrivate::emitPropertiesAssigned()", "int32_t QtMetaTypePrivate::QMetaTypeFunctionHelper::Construct(void*, void const*)", "int32_t QSharedDataPointer::data()", "void QAbstractNativeEventFilter::~QAbstractNativeEventFilter()", "int32_t QList::end()", "int32_t BinaryNinjaCore::ArchitectureWrapper::GetOpcodeDisplayLength() const", "int32_t BinaryNinjaCore::ScriptingInstance::SetCurrentSelection(uint64_t, uint64_t)", "int32_t (anonymous namespace)::TypeDestructor::DestructorImpl::Destruct(int32_t, void*)", "int32_t QGb18030Codec::_name()", "int32_t QList::detach()", "int32_t QBasicAtomicPointer >::testAndSetRelease(QFreeList*, QFreeList*)", "int32_t QJsonPrivate::Parser::reserveSpace(int32_t)", "int32_t QStateMachinePrivate::endMacrostep(bool)", "void QScopedPointer >::~QScopedPointer()", "bool QVariantIsNull<(anonymous namespace)::CoreTypesFilter>::delegate(QMatrix4x4 const*)", "void QAbstractProxyModelPrivate::QAbstractProxyModelPrivate()", "int32_t std::__1::__function::__func, void ()>::operator()()" ) for i, test in enumerate(tests): t, n = demangle_gnu3(Architecture['x86'], test) result = self.get_type_string(t, n) assert result == oracle[i], f"oracle: '{oracle[i]}'\nresult: '{result}'" class PluginManagerTest(unittest.TestCase): def test_install_plugin(self): mgr = RepositoryManager() assert mgr.check_for_updates() assert mgr.default_repository.path == 'community' assert 'community' in [r.path for r in mgr.repositories] assert 'official' in [r.path for r in mgr.repositories] assert 'Vector35_debugger' in [p.path for p in mgr['official'].plugins] try: dbg = mgr['official']['Vector35_debugger'] assert dbg.dependencies == 'colorama\n' assert dbg.name == 'Debugger' assert not dbg.installed assert not dbg.running assert not dbg.enabled assert not dbg.disable_pending dbg.install() dbg.enable() assert dbg.installed assert dbg.enabled finally: dbg.uninstall() class TypeParserTest(unittest.TestCase): def setUp(self): self.arch = 'x86_64' 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)] for name, definition, size, signed in integers: with self.subTest(): result = self.p.parse_types_from_source(definition) var = result.variables[name] assert len(var) == size, f"Size for type: {definition} != {size} for arch {self.arch}" 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), ] 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 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" 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)), ] 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" 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`'), ] 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}" got_backticks = QualifiedName.escape(source, TokenEscapingType.BackticksTokenEscapingType) assert got_backticks == expect_backticks, f"Escape test of {source} BackticksTokenEscapingType got {got_backticks} expected {expect_backticks}" got_unesc = QualifiedName.unescape(got_backticks, TokenEscapingType.BackticksTokenEscapingType) assert got_unesc == source, f"Escape test round trip for {source} got {got_unesc} from {got_backticks}, expected {source}" def test_escaped_parsing(self): valid = r''' typedef uint32_t `type name with space`; typedef `type name with space` `another name`; enum `space enum` { `space enum member 1` = 1, `space enum member 2` = 2, }; struct `space struct` { `another name` `first member`; `another name`* `second member`; `another name` (*`third member`)(`another name` `argument name`); }; ''' 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 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' assert types.types['space struct'].members[1].name == 'second member' assert types.types['space struct'].members[1].type.target.name == 'another name' assert types.types['space struct'].members[2].name == 'third member' assert len(types.types['space struct'].members[2].type.target.parameters) == 1 assert types.types['space struct'].members[2].type.target.parameters[0].name == 'argument name' class TestQualifiedName(unittest.TestCase): def test_constructors_and_equality(self): assert QualifiedName("name").name == ["name"] assert QualifiedName(b"name").name == ["name"] assert QualifiedName(QualifiedName("name")).name == ["name"] assert QualifiedName(["name1", "name2"]).name == ["name1", "name2"] assert QualifiedName([b"name1", b"name2"]).name == ["name1", "name2"] def test_comparison(self): assert QualifiedName("a") == "a" assert QualifiedName(["a", "b"]) == "a::b" assert QualifiedName("a") == ["a"] assert QualifiedName("a") == QualifiedName("a") assert QualifiedName("a").__eq__(None) == NotImplemented assert QualifiedName(["a", "b"]) != "a::a" assert QualifiedName("a") != ["b"] assert QualifiedName("a") != QualifiedName("b") assert QualifiedName("a").__ne__(None) == NotImplemented assert QualifiedName("a") < QualifiedName("b") assert QualifiedName("a").__lt__(None) == NotImplemented assert QualifiedName("a") <= QualifiedName("a") assert QualifiedName("a").__le__(None) == NotImplemented assert QualifiedName("b") > QualifiedName("a") assert QualifiedName("a").__gt__(None) == NotImplemented assert QualifiedName("a") >= QualifiedName("a") assert QualifiedName("a").__ge__(None) == NotImplemented def test_accessors(self): assert QualifiedName("a")[0] == "a" name = ["a", "b", "c"] q = QualifiedName(name) it = iter(q) assert next(it) == "a" assert next(it) == "b" assert next(it) == "c" assert q.name == name q.name = list(reversed(name)) assert q.name == list(reversed(name)) def test_str(self): name = ["a", "b", "c"] q = QualifiedName(name) assert str(q) == "::".join(name) def test_len(self): name = ["a", "b", "c"] assert len(QualifiedName(name)) == 3 class TypeTest(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_IntegerBuilder(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" assert repr(ib).startswith("") def test_NamedTypeReferenceBuilder(self): b = TypeBuilder.named_type_reference(NamedTypeReferenceClass.UnknownNamedTypeClass, "foo") assert b.name == "foo" assert b.named_type_class == NamedTypeReferenceClass.UnknownNamedTypeClass b = TypeBuilder.named_type_from_type("foobar", NamedTypeReferenceClass.UnknownNamedTypeClass) assert b.name == "foobar" assert b.id == b.type_id assert b.named_type_class == NamedTypeReferenceClass.UnknownNamedTypeClass assert b == b.immutable_copy().mutable_copy(), "NamedTypeReferenceBuilder failed to round trip mutability" b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName(b"name"), Type.int(4)) assert b.name == "name" assert b.id == "type_id" assert b.named_type_class == NamedTypeReferenceClass.TypedefNamedTypeClass assert repr(b).startswith(" -1 assert o >= 0 class TestBoolWithConfidence(unittest.TestCase): def test_constructor(self): o = BoolWithConfidence(True) assert o.value == True assert o.confidence == 255 assert bool(o) == True assert o == True assert o == BoolWithConfidence(True) assert o != BoolWithConfidence(True, 0) class TestSymbols(unittest.TestCase): def test_CoreSymbol(self): with Apparatus("helloworld") as bv: assert len(bv.symbols) == 56 sym = bv.symbols["_Jv_RegisterClasses"][0] sym2 = bv.symbols['__elf_header'][0] assert repr(sym).startswith('') assert sym == sym assert sym != sym2 assert sym.__eq__(None) == NotImplemented assert sym.__ne__(None) == NotImplemented assert hash(sym) != hash(sym2) assert sym.binding == SymbolBinding.WeakBinding assert sym.short_name == "_Jv_RegisterClasses" assert sym.full_name == "_Jv_RegisterClasses" assert sym.raw_name == "_Jv_RegisterClasses" 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 ) assert sym.binding == SymbolBinding.GlobalBinding assert sym.short_name == "short_name" assert sym.full_name == "full_name" assert sym.raw_name == "raw_name" assert sym.raw_bytes == b"raw_name" assert sym.ordinal == 2 assert not sym.auto def test_NameSpace(self): ns = NameSpace("BN_INTERNAL_NAMESPACE") assert str(ns) == str(NameSpace._from_core_struct(ns._to_core_struct())) 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" def test_attributes(self): t = self.bv.types["Elf32_Dyn"] assert t.confidence == 255 assert t.platform == self.bv.platform t.confidence = 0 assert t.confidence == 0 p = Platform["windows-x86"] t.platform = p assert t.platform == p with t.get_builder(self.bv) as s: assert isinstance(s, StructureBuilder) 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" ) assert unregistered_ntr.target(self.bv) == None class TestMutableTypeBuilder(TestWithBinaryView): def test_MutableTypeBuilder(self): with Type.builder(self.bv, "Elf32_Dyn") as b: assert isinstance(b, StructureBuilder) b.append(Type.int(4), "test_field") b = self.bv.types["Elf32_Dyn"] assert isinstance(b, StructureType) assert b.member_at_offset(8).name == "test_field" self.assertRaises(ValueError, lambda: Type.builder(self.bv, None)) with Type.builder(self.bv, None, 'elf:["Elf32_Dyn"]') as b: assert isinstance(b, StructureBuilder) b.append(Type.int(4), "test_field2") b = self.bv.types["Elf32_Dyn"] assert isinstance(b, StructureType) assert b.member_at_offset(12).name == "test_field2" self.assertRaises(ValueError, lambda: Type.builder(self.bv, None, 'not - elf:["Elf32_Dyn"]')) self.assertRaises(ValueError, lambda: Type.builder(self.bv, 'not - elf:["Elf32_Dyn"]')) 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" msg = "A Comment" addr = 0x0000845c self.func.set_comment_at(addr, msg) assert self.func.get_comment_at(addr) == msg 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) 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.get_address_tags_at(addr, self.func.arch) 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 def test_il_properties(self): lifted_il = self.func.lifted_il assert isinstance(lifted_il, LowLevelILFunction) assert lifted_il == self.func.lifted_il_if_available llil = self.func.low_level_il assert isinstance(llil, LowLevelILFunction) assert llil == self.func.llil assert llil == self.func.llil_if_available mlil = self.func.medium_level_il assert isinstance(mlil, MediumLevelILFunction) assert mlil == self.func.mlil assert mlil == self.func.mlil_if_available mmlil = self.func.llil.mapped_medium_level_il assert isinstance(mmlil, MediumLevelILFunction) assert mmlil == self.func.mmlil assert mmlil == self.func.mmlil_if_available hlil = self.func.high_level_il assert isinstance(hlil, HighLevelILFunction) assert hlil == self.func.hlil assert hlil == self.func.hlil_if_available def test_function_type(self): ft = self.func.function_type assert ft.return_value == Type.int(4) ftm = ft.mutable_copy() ftm.return_value = Type.int(4, False) self.func.function_type = ftm self.func.view.update_analysis_and_wait() assert self.func.function_type.return_value == Type.int(4, False), f"{self.func.function_type.return_value} != {Type.int(4, False)}" func_str = "int32_t main(int32_t argc, char** argv, char** envp)" self.func.function_type = func_str self.func.view.update_analysis_and_wait() ft1 = self.func.function_type ft2 = self.bv.parse_type_string(func_str)[0] # ft2's calling convention is None and thus not expected to persist assert (ft1.return_value, ft1.parameters) == (ft2.return_value, ft2.parameters), f"{ft1} != {ft2}" def test_stack_layout(self): assert len(self.func.stack_layout) == 5 assert len(self.func.core_var_stack_layout) == 5 assert isinstance(self.func.stack_layout[0], Variable) assert isinstance(self.func.core_var_stack_layout[0], CoreVariable) def test_vars(self): assert len(self.func.vars) == 10 assert len(self.func.core_vars) == 10 assert isinstance(self.func.vars[0], Variable) assert isinstance(self.func.core_vars[0], CoreVariable) def test_indirect_branches(self): assert len(self.func.indirect_branches) == 0 assert len(self.func.unresolved_indirect_branches) == 0 assert not self.func.has_unresolved_indirect_branches def test_session_data(self): # TODO pass def test_analysis_performance_info(self): # TODO is there any better way to test this? assert isinstance(self.func.analysis_performance_info['Total'], float) def test_types(self): assert str(self.func.type_tokens[0]) == "int32_t" assert str(self.func.type_tokens[2]) == "main" assert self.func.return_type == Type.int(4, True) self.func.return_type = Type.void() self.bv.update_analysis_and_wait() assert self.func.return_type == Type.void() self.func.return_type = "uint64_t" self.bv.update_analysis_and_wait() assert self.func.return_type == Type.int(8, False) self.func.return_type = Type.int(4, True) self.bv.update_analysis_and_wait() assert self.func.return_type == Type.int(4, True) assert len(self.func.return_regs.regs) == 1 assert self.func.return_regs.regs[0] == "r0" cc = self.func.calling_convention assert cc.name == 'cdecl' # clearing the calling convention makes analysis self.func.calling_convention = None self.bv.update_analysis_and_wait() assert self.func.calling_convention != None, f"{self.func.calling_convention} is None" self.func.calling_convention = cc self.bv.update_analysis_and_wait() assert self.func.calling_convention == cc self.func.mark_recent_use() def test_refs(self): from_addr = 0x0000843c to_addr = 0x00008440 self.func.add_user_code_ref(from_addr, to_addr) refs = list(self.func.view.get_code_refs(from_addr)) class TestBinaryView(TestWithBinaryView): def test_TagType(self): tt = self.bv.tag_types["Crashes"] t2 = self.bv.tag_types["Bugs"] assert repr(tt).startswith("") 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("