summaryrefslogtreecommitdiff
path: root/suite/api_test.py
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-06-14 12:20:46 -0400
committerMason Reed <mason@vector35.com>2024-06-14 12:20:46 -0400
commit3c58f74fe8e8bb9029cfe560a836303a2ce3bbdb (patch)
tree8566be9997805944141e3c745c26fdbe4bc07b3e /suite/api_test.py
parentf4eb81635006d8bbfe1a4a7550d62ae3163117a3 (diff)
Delete unmaintained test suite
Diffstat (limited to 'suite/api_test.py')
-rw-r--r--suite/api_test.py3565
1 files changed, 0 insertions, 3565 deletions
diff --git a/suite/api_test.py b/suite/api_test.py
deleted file mode 100644
index 7054008a..00000000
--- a/suite/api_test.py
+++ /dev/null
@@ -1,3565 +0,0 @@
-import unittest
-import os
-
-import binaryninja as bn
-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.enums import (
- StructureVariant, NamedTypeReferenceClass, MemberAccess, MemberScope, ReferenceType, VariableSourceType,
- SymbolBinding, SymbolType, TokenEscapingType, InstructionTextTokenType, TypeDefinitionLineType
-)
-
-from binaryninja.types import (
- QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, OffsetWithConfidence, BoolWithConfidence,
- EnumerationBuilder, NamedTypeReferenceBuilder, StructureBuilder, StructureMember, IntegerType, StructureType,
- Symbol, NameSpace, MutableTypeBuilder, NamedTypeReferenceType, QualifiedNameType, TypeDefinitionLine
-)
-from binaryninja.architecture import *
-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 *
-from binaryninja.typecontainer import *
-from binaryninja.typeparser import *
-from binaryninja.typeprinter import *
-import zipfile
-from flaky import flaky
-
-
-class FileApparatus:
- 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)
-
- @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)
-
- def __enter__(self):
- return self.path
-
- def __exit__(self, type, value, traceback):
- pass
-
-class Apparatus:
- def __init__(self, filename):
- with FileApparatus(filename) as path:
- bv = bn.load(os.path.relpath(path))
- assert bv is not None
- self.bv = bv
-
- def __del__(self):
- 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: BinaryView = self.apparatus.bv
- self.arch: Architecture = self.bv.arch
- self.plat: Platform = 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
- self.bv.remove_metadata("SomeKey")
- self.assertRaises(KeyError, lambda: self.bv.query_metadata("SomeKey"))
-
-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<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)
- result = self.get_type_string(t, n)
- assert result == oracle[i], f"oracle: '{oracle[i]}'\nresult: '{result}'"
-
-
-class PluginManagerTest(unittest.TestCase):
- @flaky(max_runs=4, min_passes=1)
- 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_Z80' in [p.path for p in mgr['official'].plugins]
- try:
- plugin = mgr['official']['Vector35_Z80']
- assert plugin.dependencies == 'z80dis\n'
- assert plugin.name == 'Z80 Architecture Plugin'
- assert not plugin.installed
- assert not plugin.running
- assert not plugin.enabled
- assert not plugin.disable_pending
- plugin.install()
- plugin.enable()
- assert plugin.installed
- assert plugin.enabled
- finally:
- plugin.uninstall()
-
-
-class TypeParserTest(unittest.TestCase):
- def setUp(self):
- self.arch = 'x86_64'
- self.p = Platform[self.arch]
- self.parser = TypeParser['ClangTypeParser']
-
- def parse_types_from_source(self, source):
- (types, errors) = self.parser.parse_types_from_source(source, "types.hpp", self.p)
- if types is None:
- raise SyntaxError('\n'.join(str(e) for e in errors))
- return BasicTypeParserResult(
- types=dict(zip([t.name for t in types.types], [t.type for t in types.types])),
- variables=dict(zip([t.name for t in types.variables], [t.type for t in types.variables])),
- functions=dict(zip([t.name for t in types.functions], [t.type for t in types.functions])),
- )
-
- 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.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.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.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.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'
-
- def test_parse_class(self):
- valid = r'''
- class foo;
- class bar
- {
- foo* foo;
- };
- class baz
- {
- class
- {
- bar m_bar;
- } bar;
- struct
- {
- baz* m_baz;
- } baz;
- };
- '''
- types = self.parse_types_from_source(valid)
- assert types.types['bar'].type_class == TypeClass.StructureTypeClass
- assert types.types['bar'].type == StructureVariant.ClassStructureType
- assert types.types['baz'].type_class == TypeClass.StructureTypeClass
- assert types.types['baz'].type == StructureVariant.ClassStructureType
- assert types.types['baz'].members[0].type.type_class == TypeClass.StructureTypeClass
- assert types.types['baz'].members[0].type.type == StructureVariant.ClassStructureType
- assert types.types['baz'].members[1].type.type_class == TypeClass.StructureTypeClass
- assert types.types['baz'].members[1].type.type == StructureVariant.StructStructureType
-
- def test_class_vs_struct(self):
- # Trying to use `class foo` as `struct foo`
-
- # Clang says (TIL):
- # "Class 'foo' was previously declared as a struct; this is valid, but may result in linker errors under the Microsoft C++ ABI"
- valid = [
- r'''
- class foo
- {
- int a;
- };
- class bar
- {
- struct foo foo;
- };
- ''', r'''
- struct foo
- {
- int a;
- };
- struct bar
- {
- class foo foo;
- };
- '''
- ]
- for source in valid:
- with self.subTest():
- types = self.parse_types_from_source(source)
-
-
- def test_parse_empty(self):
- valid = [
- # Forward declarations
- 'struct foo;',
- 'class foo;',
- 'union foo;',
- # Definition with no members
- 'struct foo {};',
- 'class foo {};',
- 'union foo {};',
- 'enum foo {};',
- # Inner structure is empty
- 'struct foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
- 'class foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
- 'union foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
- ]
- for source in valid:
- with self.subTest():
- types = self.parse_types_from_source(source)
-
- invalid = [
- # Forward declaration of enum is not allowed
- 'enum foo;'
- ]
- for source in invalid:
- with self.subTest():
- with self.assertRaises(SyntaxError):
- types = self.parse_types_from_source(source)
-
- def test_parse_nested(self):
- source = r'''
- struct foo
- {
- enum : uint32_t
- {
- a = 1,
- b = 2,
- c = 3
- } bar;
- struct
- {
- uint32_t a;
- } baz;
- class
- {
- uint32_t a;
- } alpha;
- union
- {
- uint32_t a;
- uint32_t b;
- } bravo;
- };
- '''
- types = self.parse_types_from_source(source)
- assert types.types['foo'].members[0].type.type_class == TypeClass.EnumerationTypeClass
- assert types.types['foo'].members[1].type.type_class == TypeClass.StructureTypeClass
- assert types.types['foo'].members[1].type.type == StructureVariant.StructStructureType
- assert types.types['foo'].members[2].type.type_class == TypeClass.StructureTypeClass
- assert types.types['foo'].members[2].type.type == StructureVariant.ClassStructureType
- assert types.types['foo'].members[3].type.type_class == TypeClass.StructureTypeClass
- assert types.types['foo'].members[3].type.type == StructureVariant.UnionStructureType
- assert types.types['foo'].members[0].type.members[0].name == 'a'
- assert types.types['foo'].members[0].type.members[1].name == 'b'
- assert types.types['foo'].members[0].type.members[2].name == 'c'
- assert types.types['foo'].members[1].type.members[0].name == 'a'
- assert types.types['foo'].members[2].type.members[0].name == 'a'
- assert types.types['foo'].members[3].type.members[0].name == 'a'
- assert types.types['foo'].members[3].type.members[1].name == 'b'
-
- def test_forward_declared(self):
- # Via #2431 with a little extra sauce on LIST_ENTRY1
- source = r'''
- struct _LIST_ENTRY;
- typedef struct _LIST_ENTRY LIST_ENTRY;
- typedef LIST_ENTRY LIST_ENTRY1;
- struct _LIST_ENTRY {
- LIST_ENTRY * ForwardLink;
- LIST_ENTRY * BackLink;
- };
-
- struct Test {
- long long Signature;
- LIST_ENTRY1 Link;
- int Action;
- short DefaultId;
- };
- '''
- types = self.parse_types_from_source(source)
- assert types.types['_LIST_ENTRY'].width == 0x10
- assert types.types['LIST_ENTRY'].width == 0x10
- assert types.types['LIST_ENTRY1'].width == 0x10
- assert types.types['Test'].width == 0x20
- assert types.types['Test'].members[2].offset == 0x18
-
- def test_custom_subclass(self):
- class MyTypeParser(TypeParser):
- name = "MyTypeParser"
-
- def preprocess_source(
- self, source: str, file_name: str, platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]],
- options: Optional[List[str]], include_dirs: Optional[List[str]]
- ) -> Tuple[Optional[str], List[TypeParserError]]:
- return (
- source,
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
- )
-
- def parse_types_from_source(
- self,
- source: str,
- file_name: str,
- platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]],
- options: Optional[List[str]],
- include_dirs: Optional[List[str]],
- auto_type_source: str = ""
- ) -> Tuple[Optional[TypeParserResult], List[TypeParserError]]:
- return (
- TypeParserResult(
- [
- ParsedType("my_type", Type.int(4, False), True)
- ], [
- ParsedType("my_variable", Type.int(4, False), True)
- ], [
- ParsedType("my_function", Type.function(Type.void(), []), True)
- ]
- ),
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
- )
-
- def parse_type_string(
- self, source: str, platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]]
- ) -> Tuple[Optional[Tuple[QualifiedNameType, binaryninja.Type]],
- List[TypeParserError]]:
- return (
- ("my_type", Type.int(4, False)),
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
- )
-
- MyTypeParser().register()
-
- tp = TypeParser['MyTypeParser']
- (result, errors) = tp.preprocess_source('some test source', 'source.h', Platform['windows-x86'])
- assert result is not None
- assert result == 'some test source'
-
- assert errors is not None
- assert len(errors) == 1
-
- assert errors[0].severity == TypeParserErrorSeverity.WarningSeverity
- assert errors[0].message == "Test Warning"
- assert errors[0].file_name == "sources.hpp"
- assert errors[0].line == 1
- assert errors[0].column == 1
-
- (result, errors) = tp.parse_types_from_source('some test source', 'source.h', Platform['windows-x86'])
- assert result is not None
- assert len(result.types) == 1
- assert len(result.variables) == 1
- assert len(result.functions) == 1
-
- assert result.types[0].name == 'my_type'
- assert result.types[0].type == Type.int(4, False)
- assert result.types[0].is_user
-
- assert result.variables[0].name == 'my_variable'
- assert result.variables[0].type == Type.int(4, False)
- assert result.variables[0].is_user
-
- assert result.functions[0].name == 'my_function'
- assert result.functions[0].type == Type.function(Type.void(), [])
- assert result.functions[0].is_user
-
- assert errors is not None
- assert len(errors) == 1
-
- assert errors[0].severity == TypeParserErrorSeverity.WarningSeverity
- assert errors[0].message == "Test Warning"
- assert errors[0].file_name == "sources.hpp"
- assert errors[0].line == 1
- assert errors[0].column == 1
-
- (result, errors) = tp.parse_type_string('some test source', Platform['windows-x86'])
- assert result is not None
- assert result[0] == 'my_type'
- assert result[1] == Type.int(4, False)
-
- assert errors is not None
- assert len(errors) == 1
-
- assert errors[0].severity == TypeParserErrorSeverity.WarningSeverity
- assert errors[0].message == "Test Warning"
- assert errors[0].file_name == "sources.hpp"
- assert errors[0].line == 1
- assert errors[0].column == 1
-
-
-class TestTypePrinter(unittest.TestCase):
- def test_getlines(self):
- arch = 'x86'
- platform = Platform['windows-x86']
- bv = BinaryView.new()
- bv.platform = platform
-
- types = [
- (Type.int(4), 'basic_int', 'typedef int32_t basic_int;\n'),
- (Type.array(Type.int(4), 4), 'basic_array', 'typedef int32_t basic_array[0x4];\n'),
- (Type.pointer(platform.arch, Type.array(
- Type.int(4), 4
- )), 'pointer_array', 'typedef int32_t (* pointer_array)[0x4];\n'),
- (Type.array(
- Type.pointer(platform.arch, Type.int(4)), 4
- ), 'array_pointer', 'typedef int32_t* array_pointer[0x4];\n'),
- (Type.function(
- Type.int(4), []
- ), 'basic_func', 'typedef int32_t basic_func();\n'),
- (Type.function(
- Type.int(4), [], platform.fastcall_calling_convention
- ), 'convention_func', 'typedef int32_t __fastcall convention_func();\n'),
- (Type.pointer(platform.arch, Type.function(
- Type.int(4), []
- ), True), 'const_func_pointer', 'typedef int32_t (* const const_func_pointer)();\n'),
- (Type.pointer(platform.arch, Type.function(
- Type.int(4), []
- )), 'basic_func_pointer', 'typedef int32_t (* basic_func_pointer)();\n'),
- (Type.function(
- Type.pointer(platform.arch, Type.int(4)), []
- ), 'func_returning_ptr', 'typedef int32_t* func_returning_ptr();\n'),
- (Type.structure([
- (Type.int(4), 'foo')
- ]), 'basic_struct', 'struct basic_struct\n{\n int32_t foo;\n};\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.int(4), 'foo')
- ])), 'pointer_struct', 'typedef struct { int32_t foo; }* pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.int(4)), 'foo')
- ])), 'pointer_in_pointer_struct', 'typedef struct { int32_t* foo; }* pointer_in_pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.int(4)), 'foo')
- ])), 'foo')
- ])), 'nested_pointer_struct', 'typedef struct { struct { int32_t* foo; }* foo; }* nested_pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.function(Type.int(4), [('param', Type.int(4))])), 'foo')
- ])), 'pointer_function_struct', 'typedef struct { int32_t (* foo)(int32_t param); }* pointer_function_struct;\n'),
- (Type.pointer(platform.arch, Type.enumeration(platform.arch, [
- ('one', 1)
- ])), 'pointer_enumeration', 'typedef enum {}* pointer_enumeration;\n'),
- ]
-
- for t in types:
- with self.subTest(t[1]):
- lines = t[0].get_lines(bv, t[1])
- text = ""
- for l in lines:
- for tok in l.tokens:
- text += tok.text
- text += "\n"
- assert text == t[2], f"Invalid printing of type, got {text} expected {t[2]}"
-
-
- def test_custom_subclass(self):
- class MyTypePrinter(TypePrinter):
- name = "MyTypePrinter"
-
- def get_type_tokens(self, type: types.Type, platform: Optional[Platform], name: types.QualifiedName,
- base_confidence: int, escaping: TokenEscapingType) -> List[InstructionTextToken]:
- return [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
- InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
- ]
-
- def get_type_tokens_before_name(self, type: types.Type, platform: Optional[Platform], base_confidence: int,
- parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[
- InstructionTextToken]:
- return [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
- ]
-
- def get_type_tokens_after_name(self, type: types.Type, platform: Optional[Platform], base_confidence: int,
- parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[InstructionTextToken]:
- return [
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0),
- ]
-
- def get_type_string(self, type: types.Type, platform: Optional[Platform], name: types.QualifiedName,
- escaping: TokenEscapingType) -> str:
- return f"the type is: {name} bottom text"
-
- def get_type_string_before_name(self, type: types.Type, platform: Optional[Platform],
- escaping: TokenEscapingType) -> str:
- return f"the type is: "
-
- def get_type_string_after_name(self, type: types.Type, platform: Optional[Platform],
- escaping: TokenEscapingType) -> str:
- return f" bottom text"
-
- def get_type_lines(self, type: types.Type, container: typecontainer.TypeContainer, name: types.QualifiedName,
- padding_cols, collapsed, escaping: TokenEscapingType) -> List[types.TypeDefinitionLine]:
- return [
- TypeDefinitionLine(TypeDefinitionLineType.TypedefLineType, [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
- InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
- ], type, type, type, '', 0, 1),
- ]
-
- MyTypePrinter().register()
-
- tp = TypePrinter['MyTypePrinter']
- result = tp.get_type_tokens(Type.void(), None, QualifiedName(['test']), 255, TokenEscapingType.NoTokenEscapingType)
- assert result is not None
- assert len(result) == 3
- assert result[0].text == "the type is: "
- assert result[1].text == "test"
- assert result[2].text == " bottom text"
- result = tp.get_type_tokens_before_name(Type.void())
- assert result is not None
- assert len(result) == 1
- assert result[0].text == "the type is: "
- result = tp.get_type_tokens_after_name(Type.void())
- assert result is not None
- assert len(result) == 1
- assert result[0].text == " bottom text"
- result = tp.get_type_string(Type.void(), None, QualifiedName(['test']))
- assert result is not None
- assert result == "the type is: test bottom text"
- result = tp.get_type_string_before_name(Type.void())
- assert result is not None
- assert result == "the type is: "
- result = tp.get_type_string_after_name(Type.void())
- assert result is not None
- assert result == " bottom text"
- bv = BinaryView.new(b'')
- bv.platform = Platform['windows-x86_64']
- result = tp.get_type_lines(Type.void(), bv.type_container, QualifiedName(['test']), bv.platform)
- assert result is not None
- assert len(result) == 1
- assert len(result[0].tokens) == 3
- assert result[0].tokens[0].text == "the type is: "
- assert result[0].tokens[1].text == "test"
- assert result[0].tokens[2].text == " bottom text"
-
-
-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("<type:")
-
- def test_CharBuilder(self):
- b = TypeBuilder.char("my_char")
- b.const = True
- b.volatile = False
- assert b.alternate_name == "my_char"
- b.alternate_name = "my_char2"
- assert b.const
- assert not b.volatile
- assert b.alternate_name == "my_char2"
- assert b == b.immutable_copy().mutable_copy(), "CharBuilder failed to round trip mutability"
-
- def test_FloatBuilder(self):
- b = TypeBuilder.float(4, "half")
- b.const = True
- b.volatile = False
- assert b.const
- assert not b.volatile
- assert b.alternate_name == "half"
- assert b == b.immutable_copy().mutable_copy(), "FloatBuilder failed to round trip mutability"
-
- def test_WideCharBuilder(self):
- b = TypeBuilder.wide_char(4, "wchar32_t")
- b.const = True
- b.volatile = False
- assert b.const
- assert not b.volatile
- assert b.alternate_name == "wchar32_t"
- assert b == b.immutable_copy().mutable_copy(), "WideCharBuilder failed to round trip mutability"
-
- def test_PointerBuilder(self):
- ib = TypeBuilder.int(4)
- b = TypeBuilder.pointer(self.arch, ib, 4)
- b.const = True
- b.volatile = False
- assert ib.immutable_copy() == b.immutable_target
- assert ib == b.target
- assert ib.immutable_copy() == b.child.immutable_copy()
- assert b == b.immutable_copy().mutable_copy(), "PointerBuilder failed to round trip mutability"
-
- b = TypeBuilder.pointer_of_width(4, ib)
- b.const = True
- b.volatile = False
- assert len(b) == 4
- assert ib.immutable_copy() == b.immutable_target
- assert ib == b.target
- assert ib.immutable_copy() == b.child.immutable_copy()
- assert b == b.immutable_copy().mutable_copy(), "PointerBuilder failed to round trip mutability"
- assert b.mutable_copy() == b
- assert TypeBuilder.create() == NotImplemented
-
- def test_VoidBuilder(self):
- b = TypeBuilder.void()
- assert b == b.immutable_copy().mutable_copy(), "VoidBuilder failed to round trip mutability"
-
- def test_BoolBuilder(self):
- b = TypeBuilder.bool()
- assert b == b.immutable_copy().mutable_copy(), "VoidBuilder failed to round trip mutability"
-
- def test_FunctionBuilder(self):
- bb = TypeBuilder.bool()
- ib = TypeBuilder.int(4)
- pb = TypeBuilder.pointer(self.arch, ib, 4)
- vb = TypeBuilder.void()
- b = TypeBuilder.function(vb, [FunctionParameter(pb, "arg1"), ("arg2", pb)], self.cc)
- assert b.system_call_number is None
- b.system_call_number = 1
- assert b.system_call_number == 1
- b.clear_system_call()
- assert b.system_call_number is None
- b.system_call_number = 1
-
- assert b == b.immutable_copy().mutable_copy(), "FunctionBuilder failed to round trip mutability"
- assert b.immutable_return_value == vb.immutable_copy()
- assert b.return_value == vb
- b.return_value = b
- b.append(bb)
- b.append(FunctionParameter(pb, "arg3"))
- assert b.calling_convention == self.cc
- assert b.can_return
- b.can_return = False
- assert not b.can_return
- assert b.stack_adjust == 0
- assert len(b.parameters) == 4
- assert b.parameters[0].type == pb.immutable_copy()
- assert b.parameters[0].name == "arg1"
- assert b.parameters[2].type == bb.immutable_copy()
- assert b.parameters[2].name == ""
- assert b.parameters[3].type == pb.immutable_copy()
- assert b.parameters[3].name == "arg3"
- assert b.stack_adjust.value == 0
- assert not b.variable_arguments
- b.parameters = [FunctionParameter(pb, "arg1")]
- assert b.parameters[0].type == pb.immutable_copy()
- assert b.parameters[0].name == "arg1"
- assert len(b.parameters) == 1
-
- b = TypeBuilder.function()
- assert len(b.parameters) == 0
- assert b.return_value == TypeBuilder.void()
- assert b == b.immutable_copy().mutable_copy(), "FunctionBuilder failed to round trip mutability"
-
- def test_ArrayBuilder(self):
- ib = TypeBuilder.int(4)
- b = TypeBuilder.array(ib, 4)
- assert len(b) == len(ib) * 4
- assert b.count == 4
- assert b.element_type == ib
- assert b == b.immutable_copy().mutable_copy(), "ArrayBuilder failed to round trip mutability"
-
- def test_StructureBuilder(self):
- ib = TypeBuilder.int(4)
- b = TypeBuilder.structure([StructureMember(ib, "name", 0), Type.bool()])
- b.members = [*b.members, StructureMember(ib, "name2", 8)]
- assert not b.union
- b.type = StructureVariant.UnionStructureType
- assert b.union
- b.type = StructureVariant.StructStructureType
- assert b['name'].name == "name"
- assert b['name'].type == ib.immutable_copy()
-
- assert b["doesnt exist"] is None
-
- it = iter(b)
- mem = next(it)
- assert mem.name == "name"
- assert mem.type == ib.immutable_copy()
- mem = next(it)
- assert mem.name == "field_4"
- assert mem.type == Type.bool()
- mem = next(it)
- assert mem.name == "name2"
- assert mem.type == ib.immutable_copy()
-
- assert len(b) == 12
- assert b.member_at_offset(0x1000) == None
- assert b.member_at_offset(0).name == "name"
- assert b.member_at_offset(0).type == ib.immutable_copy()
- assert b.member_at_offset(4).name == "field_4"
- assert b.member_at_offset(4).type == Type.bool()
- assert b.member_at_offset(8).name == "name2"
- assert b.member_at_offset(8).type == ib.immutable_copy()
- assert b.index_by_name("name") == 0
- assert b.index_by_name("name2") == 2
- assert b.index_by_name("doesn't exist") is None
- assert b.index_by_offset(0) == 0
- assert b.index_by_offset(4) == 1
- assert b.index_by_offset(8) == 2
- assert b.index_by_offset(0x10000) is None
- b.add_member_at_offset("foo", Type.int(4), 0x20)
- mem = b.member_at_offset(0x20)
- assert mem.name == "foo"
- assert mem.type == Type.int(4)
- assert b == b.immutable_copy().mutable_copy(), "StructureBuilder failed to round trip mutability"
-
- assert len(StructureMember(Type.int(4), "foo", 0)) == len(Type.int(4))
-
- b = TypeBuilder.union([StructureMember(ib, "name", 0), StructureMember(ib, "name2", 0)])
- assert b.type == StructureVariant.UnionStructureType
-
- b = TypeBuilder.class_type([StructureMember(ib, "name", 0), StructureMember(ib, "name2", 4)])
- assert b.type == StructureVariant.ClassStructureType
-
- def test_EnumerationBuilder(self):
- b = EnumerationBuilder.create([("Member1", 1)], 4, None, False)
- assert not b.signed
- b.signed = True
- assert b.signed
- assert len(b.members) == 1
- assert b.members[0].name == "Member1"
- assert b.members[0].value == 1
- b.members = [("Member0", 0), ("Member1")]
- assert b.members[0].name == "Member0"
- assert b.members[0].value == 0
- assert b.members[1].name == "Member1"
- assert b.members[1].value == None
-
- b.append("NewMember")
- assert b.members[2].name == "NewMember"
- assert b.members[2].value == None
- it = iter(b)
- mem = next(it)
- assert mem.name == "Member0"
- assert mem.value == 0
- mem = next(it)
- assert mem.name == "Member1"
- assert mem.value == None
- mem = next(it)
- assert mem.name == "NewMember"
- assert mem.value == None
-
- assert b["Member0"].name == "Member0"
- assert b["Member0"].value == 0
- assert b["Member1"].name == "Member1"
- assert b["Member1"].value == None
- assert b["NewMember"].name == "NewMember"
- assert b["NewMember"].value == None
- assert b[0].name == "Member0"
- assert b[0].value == 0
- assert b[1].name == "Member1"
- assert b[1].value == None
-
- mem0, mem1 = b[0:2]
- assert mem0.name == "Member0"
- assert mem0.value == 0
- assert mem1.name == "Member1"
- assert mem1.value == None
- self.assertRaises(ValueError, lambda: b[None])
-
- b["Member0"] = 4
- assert b["Member0"].value == 4
- b[1] = EnumerationMember("Member10", 10)
- 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))
-
- e1 = EnumerationMember("Member10", 10)
- assert e1.value == 10
- assert e1.name == "Member10"
- assert int(e1) == 10
- assert repr(e1).endswith("<Member10 = 0xa>")
-
- 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("<type: mutable:NamedTypeReferenceClass 'typedef")
-
- b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName(b"name"))
- assert b.name == "name"
- assert b.id == "type_id"
- assert b.named_type_class == NamedTypeReferenceClass.UnknownNamedTypeClass
- assert repr(b).startswith("<type: mutable:NamedTypeReferenceClass 'unknown")
-
- enm = TypeBuilder.enumeration(self.arch, [("Member1", 0)], 4, False)
- b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName(b"name"), enm)
- assert b.name == "name"
- assert b.id == "type_id"
- assert b.named_type_class == NamedTypeReferenceClass.EnumNamedTypeClass
- assert repr(b).startswith("<type: mutable:NamedTypeReferenceClass 'enum")
-
- str = TypeBuilder.structure([], True, StructureVariant.StructStructureType)
- b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName(b"name"), str)
- assert b.name == "name"
- assert b.id == "type_id"
- assert b.named_type_class == NamedTypeReferenceClass.StructNamedTypeClass
- assert repr(b).startswith("<type: mutable:NamedTypeReferenceClass 'struct")
-
- str = TypeBuilder.structure([], True, StructureVariant.ClassStructureType)
- b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName(b"name"), str)
- assert b.name == "name"
- assert b.id == "type_id"
- assert b.named_type_class == NamedTypeReferenceClass.ClassNamedTypeClass
- assert repr(b).startswith("<type: mutable:NamedTypeReferenceClass 'class")
-
- str = TypeBuilder.structure([], True, StructureVariant.UnionStructureType)
- b = TypeBuilder.named_type_from_type_and_id("type_id", QualifiedName([b"name", b"name"]), str)
- assert b.name == QualifiedName(["name", "name"])
- assert b.id == "type_id"
- assert b.named_type_class == NamedTypeReferenceClass.UnionNamedTypeClass
- assert repr(b).startswith("<type: mutable:NamedTypeReferenceClass 'union")
-
- b = NamedTypeReferenceBuilder.named_type(b, 4, 4)
- assert b.width == 4
- assert b.alignment == 4
-
- b = NamedTypeReferenceBuilder.named_type_from_type("name")
- b.named_type_class == NamedTypeReferenceClass.UnknownNamedTypeClass
-
- # need binary view for this one
- #b = NamedTypeReferenceBuilder.named_type_from_registered_type(bv, )
-
- def test_IntegerType(self):
- t = IntegerType.create(2, False, "", self.plat, 0)
- assert t.width == 2
- assert len(t) == 2
- assert t.alignment == 2
- assert t.__ne__(None) == NotImplemented
- assert t.offset == 0
- assert t.confidence == 0
- assert [str(i) for i in t.get_tokens()] == ["uint16_t"]
- assert [str(i) for i in t.get_tokens_before_name()] == ["uint16_t"]
- assert [str(i) for i in t.get_tokens_after_name()] == []
- assert t.platform == self.plat
- tc = t.with_confidence(255)
- assert tc.confidence == 255
-
- t = Type.int(4)
- assert t.width == 4
- assert len(t) == 4
- assert t.alignment == 4
- assert t.altname == ""
- assert t.mutable_copy().immutable_copy() == t
-
- def test_VoidType(self):
- t = Type.void()
- assert t.width == 0
- assert t.altname == ""
- assert t.mutable_copy().immutable_copy() == t
-
- def test_BoolType(self):
- t = Type.bool()
- assert t.width == 1
- assert t.altname == ""
- assert t.mutable_copy().immutable_copy() == t
-
- def test_CharType(self):
- t = Type.char()
- assert t.width == 1
- assert t.altname == ""
- assert t.mutable_copy().immutable_copy() == t
-
- t = Type.char("char_alt_name")
- assert t.width == 1
- assert t.altname == "char_alt_name"
- assert t.mutable_copy().immutable_copy() == t
-
- def test_FloatType(self):
- t = Type.float(2)
- assert str(t.tokens[0]) == "float16"
- assert len(t) == 2
- t = Type.float(4)
- assert str(t.tokens[0]) == "float"
- assert len(t) == 4
- t = Type.float(8)
- assert str(t.tokens[0]) == "double"
- assert len(t) == 8
- t = Type.float(10)
- assert str(t.tokens[0]) == "long double"
- assert len(t) == 10
- t = Type.float(16)
- assert str(t.tokens[0]) == "float128"
- assert len(t) == 16
- assert t.mutable_copy().immutable_copy() == t
-
- def test_WideCharType(self):
- t = Type.wide_char(4)
- assert len(t) == 4
- assert str(t.tokens[0]) == "wchar32"
- assert t.mutable_copy().immutable_copy() == t
-
- def test_PointerType(self):
- t = Type.pointer(self.arch, Type.int(4), True, True)
- assert t.const
- assert t.volatile
- assert t.target == Type.int(4)
- assert t.mutable_copy().immutable_copy() == t
- assert t.ref_type == ReferenceType.PointerReferenceType
- t = Type.pointer_of_width(4, Type.int(4))
- assert len(t) == 4
-
- def test_ArrayType(self):
- element_type = Type.int(4)
- t = Type.array(element_type, 4)
- assert t.count == 4
- assert len(t) == 16
- assert t.element_type == element_type
- assert t.mutable_copy().immutable_copy() == t
-
- def test_StructureType(self):
- t = Type.structure_type(StructureBuilder.create([Type.int(1)]))
- assert t.mutable_copy().immutable_copy() == t
- t = Type.structure()
- assert t.mutable_copy().immutable_copy() == t
- assert t.mutable_copy().immutable_copy() == t
- 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)
- ])
- t2 = t
- self.assertRaises(ValueError, lambda: Type.structure([None]))
- assert hash(t1) != hash(t2)
- assert t["first"].name == "first"
- assert t["second"].name == "second"
- self.assertRaises(ValueError, lambda: t["not there"])
- mem = t.member_at_offset(0)
- assert mem.name == "first"
- assert mem.type == Type.int(4)
- assert mem.access == MemberAccess.PublicAccess
- assert mem.scope == MemberScope.StaticScope
- 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)
- ])
- 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)
- ])
- 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")
- )
- 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
- t = Type.generate_named_type_reference("guid", [b"byte", b"name"])
- assert t.mutable_copy().immutable_copy() == t
-
- b = Type.named_type_reference(NamedTypeReferenceClass.UnknownNamedTypeClass, "name")
- assert b.name == "name"
- assert b.named_type_class == NamedTypeReferenceClass.UnknownNamedTypeClass
- assert repr(b).startswith("<type: immutable:NamedTypeReferenceClass 'unknown")
-
- b = Type.named_type_reference(NamedTypeReferenceClass.EnumNamedTypeClass, "name")
- assert b.name == "name"
- assert b.named_type_class == NamedTypeReferenceClass.EnumNamedTypeClass
- assert repr(b).startswith("<type: immutable:NamedTypeReferenceClass 'enum")
-
- b = Type.named_type_reference(NamedTypeReferenceClass.StructNamedTypeClass, "name")
- assert b.name == "name"
- assert b.named_type_class == NamedTypeReferenceClass.StructNamedTypeClass
- assert repr(b).startswith("<type: immutable:NamedTypeReferenceClass 'struct")
-
- b = Type.named_type_reference(NamedTypeReferenceClass.ClassNamedTypeClass, "name")
- assert b.name == "name"
- assert b.named_type_class == NamedTypeReferenceClass.ClassNamedTypeClass
- assert repr(b).startswith("<type: immutable:NamedTypeReferenceClass 'class")
-
- b = Type.named_type_reference(NamedTypeReferenceClass.UnionNamedTypeClass, "name")
- assert b.name == "name"
- 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")
- 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")
- assert b.type_id.startswith("demange")
-
- def test_EnumerationType(self):
- t = Type.enumeration_type(self.arch, EnumerationBuilder.create([("Member1", 1)]))
- t2 = Type.enumeration_type(self.arch, EnumerationBuilder.create([("Member2", 2)]))
- assert t.mutable_copy().immutable_copy() == t
- assert t.members[0].name == "Member1"
- assert t.members[0].value == 1
- self.assertRaises(ValueError, lambda: Type.enumeration())
- self.assertRaises(ValueError, lambda: Type.enumeration(width=0))
- t = t.generate_named_type_reference("guid", "name")
- assert t.type_id == "guid"
- assert t.name == "name"
- assert hash(t2) != hash(t)
- assert Type.enumeration(members=[EnumerationMember("asdf")], width=4).members[0].value is None
-
- def test_FunctionType(self):
- t = Type.function()
- assert t.mutable_copy().immutable_copy() == t
- self.assertRaises(ValueError, lambda: t.mutable_copy() == t)
-
- vnt = VariableNameAndType(VariableSourceType.StackVariableSourceType, 0, 0, "arg1", Type.int(4))
- param1 = FunctionParameter(Type.int(4), "arg1", vnt)
- vnt = VariableNameAndType(VariableSourceType.RegisterVariableSourceType, 0, 0, "arg2", Type.int(4))
- param2 = FunctionParameter(Type.int(4), "arg2", vnt)
- vnt = VariableNameAndType(VariableSourceType.FlagVariableSourceType, 0, 0, "arg3", Type.int(4))
- param3 = FunctionParameter(Type.int(4), "arg3", vnt)
- t = Type.function(Type.void(), [param1, param2, param3], self.cc)
- assert param3 == param3.mutable_copy().immutable_copy()
- assert repr(param3).endswith(param3.name)
- assert t.mutable_copy().immutable_copy() == t
- assert t.stack_adjustment == 0
- assert t.return_value == Type.void()
- assert t.calling_convention == self.cc
- assert not t.has_variable_arguments
- assert t.can_return
-
-
-class TestOffsetWithConfidence(unittest.TestCase):
- def test_constructor(self):
- o = OffsetWithConfidence(0)
- assert o.value == 0
- assert o.confidence == 255
- assert int(o) == 0
- assert o == 0
- assert o == OffsetWithConfidence(0)
- assert o != OffsetWithConfidence(0, 0)
- assert o < 1
- assert o <= 0
- assert o > -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('<ExternalSymbol: "_Jv_RegisterClasses" @ 0x11038>')
- 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
-
- def test_enum_printing(self):
- """
- Make sure that printing different size/signedness enum values do the right thing
- """
-
- def type_to_def(bv: 'BinaryView', ty: 'Type') -> str:
- lines = ty.get_lines(bv, 'foo')
- defn = ""
- for line in lines:
- line_str = ""
- for token in line.tokens:
- if token.type == InstructionTextTokenType.IndentationToken:
- line_str += "\t"
- else:
- line_str += token.text
- if defn != "":
- defn += "\n"
- defn += line_str
- return defn
-
- with Apparatus("helloworld") as bv:
- # 0
- i8_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 1, sign=True))
- assert type_to_def(bv, i8_0) == "enum foo : char\n{\n\tfoo = 0x0\n};"
- i16_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 2, sign=True))
- assert type_to_def(bv, i16_0) == "enum foo : int16_t\n{\n\tfoo = 0x0\n};"
- i32_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 4, sign=True))
- assert type_to_def(bv, i32_0) == "enum foo : int32_t\n{\n\tfoo = 0x0\n};"
- i64_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 8, sign=True))
- assert type_to_def(bv, i64_0) == "enum foo : int64_t\n{\n\tfoo = 0x0\n};"
-
- u8_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 1, sign=False))
- assert type_to_def(bv, u8_0) == "enum foo : uint8_t\n{\n\tfoo = 0x0\n};"
- u16_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 2, sign=False))
- assert type_to_def(bv, u16_0) == "enum foo : uint16_t\n{\n\tfoo = 0x0\n};"
- u32_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 4, sign=False))
- assert type_to_def(bv, u32_0) == "enum foo : uint32_t\n{\n\tfoo = 0x0\n};"
- u64_0 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0)], 8, sign=False))
- assert type_to_def(bv, u64_0) == "enum foo : uint64_t\n{\n\tfoo = 0x0\n};"
-
- # Most positive integer
- i8_imax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x7f)], 1, sign=True))
- assert type_to_def(bv, i8_imax) == "enum foo : char\n{\n\tfoo = 0x7f\n};"
- i16_imax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x7fff)], 2, sign=True))
- assert type_to_def(bv, i16_imax) == "enum foo : int16_t\n{\n\tfoo = 0x7fff\n};"
- i32_imax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x7fffffff)], 4, sign=True))
- assert type_to_def(bv, i32_imax) == "enum foo : int32_t\n{\n\tfoo = 0x7fffffff\n};"
- i64_imax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x7fffffffffffffff)], 8, sign=True))
- assert type_to_def(bv, i64_imax) == "enum foo : int64_t\n{\n\tfoo = 0x7fffffffffffffff\n};"
-
- u8_umax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0xff)], 1, sign=False))
- assert type_to_def(bv, u8_umax) == "enum foo : uint8_t\n{\n\tfoo = 0xff\n};"
- u16_umax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0xffff)], 2, sign=False))
- assert type_to_def(bv, u16_umax) == "enum foo : uint16_t\n{\n\tfoo = 0xffff\n};"
- u32_umax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0xffffffff)], 4, sign=False))
- assert type_to_def(bv, u32_umax) == "enum foo : uint32_t\n{\n\tfoo = 0xffffffff\n};"
- u64_umax = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0xffffffffffffffff)], 8, sign=False))
- assert type_to_def(bv, u64_umax) == "enum foo : uint64_t\n{\n\tfoo = 0xffffffffffffffff\n};"
-
- # -1
- i8_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -1)], 1, sign=True))
- assert type_to_def(bv, i8_n1) == "enum foo : char\n{\n\tfoo = -0x1\n};"
- i16_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -1)], 2, sign=True))
- assert type_to_def(bv, i16_n1) == "enum foo : int16_t\n{\n\tfoo = -0x1\n};"
- i32_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -1)], 4, sign=True))
- assert type_to_def(bv, i32_n1) == "enum foo : int32_t\n{\n\tfoo = -0x1\n};"
- i64_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -1)], 8, sign=True))
- assert type_to_def(bv, i64_n1) == "enum foo : int64_t\n{\n\tfoo = -0x1\n};"
-
- # Unsigned equivalent of -1
- u8_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x80)], 1, sign=False))
- assert type_to_def(bv, u8_n1) == "enum foo : uint8_t\n{\n\tfoo = 0x80\n};"
- u16_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x8000)], 2, sign=False))
- assert type_to_def(bv, u16_n1) == "enum foo : uint16_t\n{\n\tfoo = 0x8000\n};"
- u32_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x80000000)], 4, sign=False))
- assert type_to_def(bv, u32_n1) == "enum foo : uint32_t\n{\n\tfoo = 0x80000000\n};"
- u64_n1 = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", 0x8000000000000000)], 8, sign=False))
- assert type_to_def(bv, u64_n1) == "enum foo : uint64_t\n{\n\tfoo = 0x8000000000000000\n};"
-
- # Most negative integer
- i8_imin = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -0x80)], 1, sign=True))
- assert type_to_def(bv, i8_imin) == "enum foo : char\n{\n\tfoo = -0x80\n};"
- i16_imin = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -0x8000)], 2, sign=True))
- assert type_to_def(bv, i16_imin) == "enum foo : int16_t\n{\n\tfoo = -0x8000\n};"
- i32_imin = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -0x80000000)], 4, sign=True))
- assert type_to_def(bv, i32_imin) == "enum foo : int32_t\n{\n\tfoo = -0x80000000\n};"
- i64_imin = Type.enumeration_type(bv.arch, EnumerationBuilder.create([("foo", -0x8000000000000000)], 8, sign=True))
- assert type_to_def(bv, i64_imin) == "enum foo : int64_t\n{\n\tfoo = -0x8000000000000000\n};"
-
-
-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_str(self):
- assert str(self.func) == "int32_t main(int32_t argc, char** argv, char** envp)"
-
- def test_indexing(self):
- first_block = self.func[0]
- assert first_block.start == self.func.start
- assert first_block.start == 0x8440
-
- second_third = self.func[1:3]
- assert second_third[0].start == 0x846c
- assert second_third[1].start == 0x8460
-
- self.assertRaises(IndexError, lambda: self.func[5])
- self.assertRaises(IndexError, lambda: self.func[3:6])
- self.assertRaises(ValueError, lambda: self.func['beans'])
-
- 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 == len(self.func.user_function_tags)
- 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
-
- assert 1 == len(self.func.get_function_tags_of_type(tt3))
- assert 1 == len(self.func.get_user_function_tags_of_type(tt4))
- assert 0 == len(self.func.get_auto_function_tags_of_type(tt4))
-
- 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 == len(self.func.auto_function_tags)
- 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
-
- t = self.func.create_auto_address_tag(addr, tt2, msg2, True)
- t = self.func.create_auto_address_tag(addr + 4, tt2, msg2, True)
- t = self.func.create_user_address_tag(addr, tt1, msg1, True)
-
- assert 2 == len(self.func.auto_address_tags)
- assert 1 == len(self.func.user_address_tags)
-
- range = variable.AddressRange(addr, 0x8480)
- all_at = self.func.get_address_tags_in_range(range)
- auto_at = self.func.get_auto_address_tags_in_range(range)
- user_at = self.func.get_user_address_tags_in_range(range)
-
- assert len(all_at) == 3
- assert len(auto_at) == 2
- assert len(user_at) == 1
-
- assert 1 == len(self.func.get_auto_address_tags_at(addr))
- assert 1 == len(self.func.get_user_address_tags_at(addr))
-
- assert 1 == len(self.func.get_address_tags_of_type(addr, tt2))
- assert 0 == len(self.func.get_user_address_tags_of_type(addr, tt2))
- assert 1 == len(self.func.get_address_tags_of_type(addr, tt1))
- assert 0 == len(self.func.get_auto_address_tags_of_type(addr, tt1))
-
- t = self.func.create_user_address_tag(addr, tt2, msg1, True)
- self.func.remove_user_address_tags_of_type(addr, tt2)
- assert 0 == len(self.func.get_user_address_tags_of_type(addr, tt2))
- assert 1 == len(self.func.get_user_address_tags_of_type(addr, tt1))
-
- self.func.remove_auto_address_tags_of_type(addr, tt2)
- assert 0 == len(self.func.get_auto_address_tags_of_type(addr, tt2))
-
-
- 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_misc_properties(self):
- callees = self.func.callees
- assert len(callees) == 2
-
- callers = self.func.callers
- assert len(callers) == 2
- assert callees[0].start == 0x82dc
- assert callees[1].start == 0x82dc
-
- 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)
- assert not ft.user_type
- self.func.function_type = ftm
- assert ft.user_type
- 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))
-
- f = self.bv.get_functions_by_name("puts")[0]
- refs = list(f.caller_sites)
- assert len(refs) == 2
- assert str(refs[0].llil) == 'call(0x82dc)'
- assert str(refs[1].llil) == 'call(0x82dc)'
-
- assert str(refs[0].mlil) == '0x82dc("helloworld")'
- assert str(refs[1].mlil) == '0x82dc("goodbyeworld")'
-
- assert str(refs[0].hlil) == 'puts("helloworld")'
- assert str(refs[1].hlil) == 'puts("goodbyeworld")'
-
- def test_reg_values(self):
- r0 = self.bv.arch.get_reg_index('r0')
- r3 = self.bv.arch.get_reg_index('r3')
-
- r3_after = self.func.get_reg_value_after(0x8474, r3);
- r0_after = self.func.get_reg_value_after(0x8478, r0);
- r3_at = self.func.get_reg_value_at(0x847c, r3);
- r0_at = self.func.get_reg_value_at(0x847c, r0);
-
- assert r0_after == r0_at
- assert r0_at == 0
-
- assert r3_after == r3_at
- assert r3_at == 0
-
- def test_pvs(self):
- func = self.func
-
- def first_var_by_name(name):
- return [v for v in func.vars if v.name == name][0]
-
- var_10 = first_var_by_name('var_10')
- r3 = first_var_by_name('r3')
-
- func.set_user_var_value(var_10, 0x8450, PossibleValueSet.constant_ptr(0x100))
- func.set_user_var_value(r3, 0x8454, PossibleValueSet.constant(0))
-
- all_vals = func.get_all_user_var_values()
- assert len(all_vals) == 2
- assert all_vals[var_10][ArchAndAddr(func.arch, 0x8450)] == PossibleValueSet.constant_ptr(0x100)
- assert all_vals[r3][ArchAndAddr(func.arch, 0x8454)] == PossibleValueSet.constant(0)
-
- func.clear_user_var_value(var_10, 0x8450)
- all_vals = func.get_all_user_var_values()
- assert len(all_vals) == 1
-
- func.set_user_var_value(var_10, 0x8450, PossibleValueSet.constant_ptr(0x100))
- all_vals = func.get_all_user_var_values()
- assert len(all_vals) == 2
-
- func.clear_all_user_var_values()
- all_vals = func.get_all_user_var_values()
- assert len(all_vals) == 0
-
- def test_auto_user(self):
- params = self.func.parameter_vars
- assert params[0].name == "argc"
- assert params[1].name == "argv"
- assert params[2].name == "envp"
-
- # Parameter variables
- new_params = params[0:2]
- self.func.set_auto_parameter_vars(new_params)
- self.bv.update_analysis()
- assert len(self.func.parameter_vars) == 2
- assert self.func.parameter_vars[0] == new_params[0]
- assert self.func.parameter_vars[1] == new_params[1]
-
- self.func.parameter_vars = [params[2]]
- self.bv.update_analysis_and_wait()
- assert len(self.func.parameter_vars) == 1
- assert self.func.parameter_vars[0] == params[2]
-
- # Can return
- self.func.set_auto_can_return(False)
- self.bv.update_analysis()
- assert self.func.can_return == False
-
- self.func.can_return = True
- self.bv.update_analysis_and_wait()
- assert self.func.can_return == True
-
- # Has variable arguments
- self.func.set_auto_has_variable_arguments(False)
- self.bv.update_analysis()
- assert self.func.has_variable_arguments == False
-
- self.func.has_variable_arguments = True
- self.bv.update_analysis_and_wait()
- assert self.func.has_variable_arguments == True
-
- # Stack adjustment
- self.func.set_auto_stack_adjustment(2)
- self.bv.update_analysis()
- assert self.func.stack_adjustment == 2
-
- self.func.stack_adjustment = 4
- self.bv.update_analysis_and_wait()
- assert self.func.stack_adjustment == 4
-
- # Return type
- rt = Type.int(2)
- rt2 = Type.int(4)
- self.func.set_auto_return_type(rt)
- assert self.func.return_type == rt
- self.func.return_type = rt2
- self.bv.update_analysis_and_wait()
- assert self.func.return_type == rt2
-
- # Indirect branches
- self.func.set_auto_indirect_branches(0x844c, [(self.func.arch, 0x842c)])
- assert len(self.func.indirect_branches) >= 1
- self.func.set_user_indirect_branches(0x844c, [(self.func.arch, 0x8428), (self.func.arch, 0x842c)])
- assert len(self.func.indirect_branches) >= 2
-
- def test_text_renderer(self):
- opts = DisassemblySettings()
- opts.width = 160
- opts.set_option(DisassemblyOption.ShowOpcode)
- assert opts.width == 160
- assert opts.is_option_set(DisassemblyOption.ShowOpcode) == True
-
- dtr = DisassemblyTextRenderer(self.func.hlil, opts)
- assert dtr.il_function == self.func.hlil
- dtr = DisassemblyTextRenderer(self.func.mlil, opts)
- assert dtr.il_function == self.func.mlil
- dtr = DisassemblyTextRenderer(self.func.llil, opts)
- assert dtr.il_function == self.func.llil
- assert dtr.function == self.func
- assert dtr.il == True
-
- annotations = dtr.get_instruction_annotations(0)
- assert annotations != None
-
- (line, _) = next(dtr.get_instruction_text(0))
- assert line
-
- (line, _) = next(dtr.get_disassembly_text(0))
- assert line
-
- pp_lines = dtr.post_process_lines(0, 160, [line])
- assert pp_lines != None
-
- itt = InstructionTextToken(InstructionTextTokenType.TextToken, "beans")
- dtr.add_integer_token(line.tokens, itt, 0)
- dtr.wrap_comment(line.tokens, line, "beans", False)
-
-
-class TestBinaryView(TestWithBinaryView):
- def setUp(self):
- # Switch to clang by default for these tests, since they rely on it
- self.original_parser = Settings().get_string("analysis.types.parserName")
- Settings().set_string("analysis.types.parserName", "ClangTypeParser")
- super().setUp()
-
- def tearDown(self) -> None:
- Settings().set_string("analysis.types.parserName", self.original_parser)
- super().tearDown()
-
- 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)
-
- def test_log_api(self):
- bn.log.log_info("If this doesn't work then you `from .log import log` somewhere you shouldn't`")
- assert bn.log.is_output_redirected_to_log
- logger = bn.log.Logger(0, "test_logger")
- logger.log(LogLevel.DebugLog, "debug log")
- logger.log_info("log info")
- logger.log_debug("log debug")
-
- def test_sections(self):
- sections = self.bv.sections
- assert len(sections) == 25, f"section count is {len(sections)} not 25"
- section = sections['.ARM.exidx']
- section2 = sections['.bss']
- assert repr(section) == "<section .ARM.exidx: 0x851c-0x8524>"
- assert len(section) == 8
- assert section == section
- assert section != section2
- assert hash(section) != hash(section2)
- assert hash(section) == hash(section)
- assert section.start in section
- assert section.name == '.ARM.exidx'
- assert section.start == 0x851c
- assert section.linked_section == '.text'
- assert section.info_section == ''
- assert section.info_data == 0
- assert section.align == 4
- assert section.entry_size == 0
- assert section.semantics == SectionSemantics.ReadOnlyDataSectionSemantics
- assert section.auto_defined
- assert section.end == 0x8524
- assert section.type == ''
-
- def test_segments(self):
- segments = self.bv.segments
- segment = segments[0]
- assert len(segments) == 3
- assert len(segment) == 1320
- assert segment == segment
- assert segment != segments[1]
- assert segment.start in segment
- assert segment.start == 0x8000
- assert segment.end == 0x8528
- assert segment.readable
- assert not segment.writable
- assert segment.executable
- assert segment.data_length == 0x528
- assert segment.data_offset == 0x0
- assert segment.data_end == 0x8528
- assert segment.auto_defined
- assert segment.relocation_count == 0
- s2 = segments[1]
- assert s2.relocation_count == 5
- assert s2.relocation_ranges == [(69644, 69648), (69648, 69652), (69652, 69656), (69656, 69660), (69660, 69664)]
- assert s2.relocation_ranges_at(69644) == [(69644, 69648)]
- assert hash(segment) != hash(s2)
-
- def test_binary_data_nofification_default(self):
- bv = self.bv
-
- global results
- results = None
- def simple_complete(self):
- global results
- results = "analysis complete"
- event = bn.AnalysisCompletionEvent(bv, simple_complete)
- bv.update_analysis_and_wait()
- assert results == "analysis complete"
-
- class NotifyTest(bn.BinaryDataNotification):
- pass
-
- test = NotifyTest()
- bv.register_notification(test)
- sacrificial_addr = 0x84fc
-
- type, name = bv.parse_type_string("int foo")
- type_id = Type.generate_auto_type_id("source", name)
-
- bv.define_type(type_id, name, type) # trigger type_defined
- bv.undefine_type(type_id) # trigger type_undefined
- bv.insert(sacrificial_addr, b"AAAA") # trigger data_inserted
- bv.define_data_var(sacrificial_addr, bn.types.Type.int(4)) # trigger data_var_added
- bv.write(sacrificial_addr, b"BBBB") # trigger data_written
- bv.add_function(sacrificial_addr) # trigger function_added
- bv.remove_function(bv.get_function_at(sacrificial_addr)) # trigger function_removed
- bv.undefine_data_var(sacrificial_addr) # trigger data_var_removed
- bv.remove(sacrificial_addr, 4) # trigger data_removed
-
- type, _ = bv.parse_type_string("struct { uint64_t bar; }")
- bv.define_user_type('foo', type)
- bv.define_user_type('bar', "struct { uint64_t bas; }")
- func = bv.get_function_at(0x8440)
- func.return_type = bn.Type.named_type_from_type('foo', type)
- func.name = "foobar" # trigger symbol_added
- func.name = "" # trigger symbol_removed
-
- msg1 = "Bugs here"
- name1 = "Bugs"
- tt1 = self.bv.tag_types[name1]
- tag1 = func.create_tag(tt1, msg1, True)
-
- assert len(func.function_tags) == 0
- func.add_user_function_tag(tag1)
- t = func.create_user_function_tag(tt1, msg1, True)
- tags = func.function_tags
- assert tags[0].data == msg1
- assert tags[0].type == tt1
- func.remove_user_function_tag(tags[0])
-
- bv.update_analysis_and_wait()
- bv.unregister_notification(test)
-
- def test_strings(self):
- string = self.bv.strings[0]
- assert repr(string) == '<AsciiString: 0x8154, len 0x12>', repr(string)
- assert string.value == '/lib/ld-linux.so.3'
- assert string.value == str(string)
- assert len(string) == 18
- assert isinstance(string.raw, bytes)
- assert string.type == StringType.AsciiString
- assert string.length == 18
- assert string.view.name == self.bv.name
-
- def test_analysis_info(self):
- ap = self.bv.analysis_progress
- assert str(ap) == "Idle"
- assert repr(ap) == "<progress: Idle>"
- ai = self.bv.analysis_info
- assert repr(ai) == "<AnalysisInfo 2, analysis_time 0, active_info []>"
- ap = AnalysisProgress(AnalysisState.InitialState, 0, 0)
- assert str(ap) == "Initial"
- ap = AnalysisProgress(AnalysisState.HoldState, 0, 0)
- assert str(ap) == "Hold"
- ap = AnalysisProgress(AnalysisState.DisassembleState, 0, 0)
- assert str(ap).startswith("Disassembling")
- ap = AnalysisProgress(AnalysisState.AnalyzeState, 0, 0)
- assert str(ap).startswith("Analyzing")
- ap = AnalysisProgress(-1, 0, 0)
- assert str(ap) == "Extended Analysis"
-
- def test_symbolmapping(self):
- syms = self.bv.symbols
- assert repr(syms).startswith('<SymbolMapping ')
- assert next(self.bv.symbols)[0].name == "__elf_header"
- assert next(iter(self.bv.symbols)) == "__elf_header"
- assert "__elf_header" in syms
- for a in self.bv.symbols.keys():
- assert a == "__elf_header"
- break
- for a in self.bv.symbols.values():
- assert a[0].name == "__elf_header"
- break
- for a, b in self.bv.symbols.items():
- assert a == b[0].name
- break
- assert syms.get("__elf_header")[0].name == "__elf_header"
- assert syms.get("not_a_symbol", 0x41414141) == 0x41414141
- assert "foobar" not in syms
-
- def test_typemapping(self):
- tm = self.bv.types
- assert repr(tm).startswith("<TypeMapping")
- self.assertRaises(KeyError, lambda: tm["not a type"])
- self.assertRaises(KeyError, lambda: self.bv.types["not a type"])
- assert next(iter(tm))[0] == 'Elf32_Dyn'
- assert 'Elf32_Dyn' in self.bv.types
- assert 'asldkfjasd' not in self.bv.types
- assert tm == tm
- assert not (tm != tm)
- for a in self.bv.types.keys():
- assert a == "Elf32_Dyn"
- break
- for a in self.bv.types.values():
- assert a.registered_name.name == "Elf32_Dyn"
- break
- for a, b in self.bv.types.items():
- assert a == b.registered_name.name
- break
- assert tm.get("Elf32_Dyn").registered_name.name == "Elf32_Dyn"
- assert tm.get("not a type", 0x41414141) == 0x41414141
-
- def test_functionlist(self):
- bv = self.bv
- assert bv.functions[0] == bv.functions[0:1][0]
- self.assertRaises(IndexError, lambda: bv.functions[100000000])
- self.assertRaises(IndexError, lambda: bv.functions[0:100000000])
- self.assertRaises(ValueError, lambda: bv.functions["asdf"])
-
- def test_datavariable(self):
- dv = self.bv.data_vars[0x11048] #extern puts
- dv2 = self.bv.data_vars[0x1100c] # .got entry puts
- dv3 = self.bv.data_vars[0x8000] # elf header
-
- assert list(dv.data_refs) == [0x1100c]
- assert list(dv2.data_refs_from) == [0x11048]
- ref = list(dv2.code_refs)[0]
- assert ref.address == 0x82e4
- assert len(dv2) == 4
- assert dv.value is None
- assert dv2.value == dv.address
- assert dv2.type.type_class == TypeClass.PointerTypeClass
- assert dv3['ident']['os'].value == 0
- assert dv3.value["ident"]["os"] == 0
- dv3['ident']['os'].value = 1
- assert dv3['ident']['os'].value == 1
- assert dv3.symbol.name == "__elf_header"
- assert dv3.name == dv3.symbol.name
- dv3.name = "foo"
- assert dv3.name == "foo"
- dv3.name = ""
- assert dv3.name == "__elf_header"
- assert dv3.symbol.type == SymbolType.DataSymbol
- dv3.symbol = Symbol(SymbolType.ImportedDataSymbol, dv3.address, "foobar")
- assert dv3.name == "foobar"
- assert dv3.symbol.type == SymbolType.ImportedDataSymbol
- assert len(dv3._accessor) == 52
- dv.type = dv2.type
- assert dv.type.type_class == dv2.type.type_class
- assert dv.auto_discovered
- dv4 = self.bv.data_vars[0x00010f14]
- assert dv4.value == 0
- dv4.value = 1
- assert dv4.value == 1
- assert self.bv.data_vars[0x0000850c].name is None
-
- here = 0x10fd8
- self.bv.define_data_var(here, "float16")
- assert self.bv.data_vars[here].value == 0.0
- assert len(self.bv.data_vars[here]) == 2
- self.bv.data_vars[here].value = 2.0
- assert self.bv.data_vars[here].value == 2.0
- self.bv.data_vars[here].value = 0.0
- self.bv.define_data_var(here, "float")
- assert self.bv.data_vars[here].value == 0.0
- assert len(self.bv.data_vars[here]) == 4
- self.bv.data_vars[here].value = 2.0
- assert self.bv.data_vars[here].value == 2.0
- self.bv.data_vars[here].value = 0.0
- self.bv.define_data_var(here, "double")
- assert self.bv.data_vars[here].value == 0.0
- assert len(self.bv.data_vars[here]) == 8
- self.bv.data_vars[here].value = 2.0
- assert self.bv.data_vars[here].value == 2.0
- self.bv.data_vars[here].value = 0.0
-
- self.bv.define_data_var(here, "bool")
- assert not self.bv.data_vars[here].value
- self.bv.data_vars[here].value = True
- assert self.bv.data_vars[here].value
- self.bv.data_vars[here].value = False
-
- self.bv.define_data_var(here, "wchar16 foo[4]")
- self.bv.data_vars[here].value = "fooo".encode("utf-16-le")
- assert self.bv.data_vars[here].value == "fooo"
- self.bv.data_vars[here].value = b"\x00" * 8
-
- self.bv.define_data_var(here, "wchar16")
- self.bv.data_vars[here].value = "A".encode("utf-16-le")
- assert self.bv.data_vars[here].value == "A"
- self.bv.data_vars[here].value = b"\x00"
-
- self.bv.define_data_var(here, "struct marplehead { int x; int y;}") # Stella named this type
- assert self.bv.data_vars[here]["x"].value == 0
- self.bv.data_vars[here]["x"].value = -1
- assert self.bv.data_vars[here]["x"].value == -1
- self.bv.data_vars[here]["x"].value = 0
- assert self.bv.data_vars[here].value["x"] == 0
-
- self.bv.define_data_var(here, "enum barplehead : uint64_t { FOO = 0, BAR = 2 }") # Stella named this type
- assert self.bv.data_vars[here].value.value == 0
- self.bv.data_vars[here].value = 2
- assert self.bv.data_vars[here].value.value == 2
- self.bv.data_vars[here].value = 0
-
- self.bv.define_data_var(here, "uint8_t farplehead[8]") # Stella named this type
- assert self.bv.data_vars[here].value == b"\x00" * 8
- self.bv.data_vars[here].value = b"\xff" * 8
- assert self.bv.data_vars[here].value == b"\xff" * 8
- self.bv.data_vars[here].value = b"\x00" * 8
-
- self.bv.define_data_var(here, "int32_t garplehead[2]") # Stella named this type
- assert self.bv.data_vars[here].value == [0, 0]
- assert self.bv.data_vars[here][0].value == 0
- self.bv.data_vars[here].value = b"\xff" * 8
- assert self.bv.data_vars[here].value == [-1, -1]
- assert self.bv.data_vars[here][0].value == -1
- self.bv.data_vars[here].value = b"\x00" * 8
-
- def test_libraries(self):
- assert self.bv.libraries == ['libc.so.6']
-
- def test_reader_writer(self):
- r = self.bv.reader(self.bv.start)
- w = self.bv.writer(self.bv.start)
- r2 = self.bv.reader(self.bv.end)
- assert not self.bv.modified
- assert r.read8(self.bv.start) == 127
- assert r.read16(self.bv.start) == 17791
- assert r.read32(self.bv.start) == 1179403647
- assert r.read64(self.bv.start) == 282579962709375
- assert r.read(8, self.bv.start) == b'\x7fELF\x01\x01\x01\x00'
-
- # Also test the bv.__getitem__ as its very similar
- assert self.bv[self.bv.start:self.bv.start+8] == b'\x7fELF\x01\x01\x01\x00'
- assert self.bv[self.bv.start] == b'\x7f'
- assert self.bv[(self.bv.start + 1, self.bv.start + 3)] == b'EF'
- self.assertRaises(IndexError, lambda:self.bv[0:1:4])
- assert self.bv[self.bv.start + 8:self.bv.start + 0] == b''
- assert self.bv[-5:-1] == b'\x00\x00\x00\x00'
- self.assertRaises(IndexError, lambda: self.bv[-1000000000000])
- self.assertRaises(IndexError, lambda: self.bv[0x8529]) # past the end of a segment
- self.assertRaises(IndexError, lambda: self.bv[0x8529-self.bv.end]) # past the end of a segment
- assert 0x8527 in self.bv
- assert 0x8529 not in self.bv
-
- assert r.read16le(self.bv.start) == 17791
- assert r.read32le(self.bv.start) == 1179403647
- assert r.read64le(self.bv.start) == 282579962709375
- assert r.read16be(self.bv.start) == 32581
- assert r.read32be(self.bv.start) == 2135247942
- assert r.read64be(self.bv.start) == 9170820079758147840
-
- assert r.endianness == Endianness.LittleEndian
- r.endianness = Endianness.BigEndian
- assert r.endianness == Endianness.BigEndian
-
- assert r.read8(self.bv.start) == 127
- assert r.read16(self.bv.start) == 32581
- assert r.read32(self.bv.start) == 2135247942
- assert r.read64(self.bv.start) == 9170820079758147840
- assert r.read(8, self.bv.start) == b'\x7fELF\x01\x01\x01\x00'
- assert r.read16le(self.bv.start) == 17791
- assert r.read32le(self.bv.start) == 1179403647
- assert r.read64le(self.bv.start) == 282579962709375
- assert r.read16be(self.bv.start) == 32581
- assert r.read32be(self.bv.start) == 2135247942
- assert r.read64be(self.bv.start) == 9170820079758147840
-
- assert r.read8(self.bv.end) is None
- assert r.read16(self.bv.end) is None
- assert r.read32(self.bv.end) is None
- assert r.read64(self.bv.end) is None
- assert r.read(8, self.bv.end) is None
- assert r.read16le(self.bv.end) is None
- assert r.read32le(self.bv.end) is None
- assert r.read64le(self.bv.end) is None
- assert r.read16be(self.bv.end) is None
- assert r.read32be(self.bv.end) is None
- assert r.read64be(self.bv.end) is None
-
- assert r == r
- assert r != r2
- assert hash(r) == hash(r)
- assert hash(r) != hash(r2)
- r.offset = self.bv.start
- assert r.offset == self.bv.start
- r.read8()
- assert r.offset == self.bv.start + 1
- r.offset += 1
- assert r.offset == self.bv.start + 2
- assert not r.eof
- r.offset = self.bv.end
- assert r.eof
- r.seek(self.bv.start)
- assert r.offset == self.bv.start
- r.seek_relative(1)
- assert r.offset == self.bv.start + 1
-
- w2 = self.bv.writer(self.bv.end)
- assert w == w
- assert w != w2
- assert hash(w) != hash(w2)
- assert w.endianness == Endianness.LittleEndian
-
- w.write8(0x41, self.bv.start)
- assert r.read8(self.bv.start) == 0x41
- w.write16(0x4242, self.bv.start)
- assert r.read16(self.bv.start) == 0x4242
- w.write32(0x43434343, self.bv.start)
- assert r.read32(self.bv.start) == 0x43434343
- w.write64(0x4444444444444444, self.bv.start)
- assert r.read64(self.bv.start) == 0x4444444444444444
-
- w.offset = self.bv.start
- assert w.offset == self.bv.start
- w.write8(4)
- assert w.offset == self.bv.start + 1
- w.offset += 1
- assert w.offset == self.bv.start + 2
- w.seek(self.bv.start)
- assert w.offset == self.bv.start
- w.seek_relative(1)
- assert w.offset == self.bv.start + 1
-
- w.write8(0x41, self.bv.start)
- assert r.read8(self.bv.start) == 0x41
- w.write16(0x4242, self.bv.start)
- assert r.read16(self.bv.start) == 0x4242
- w.write32(0x43434343, self.bv.start)
- assert r.read32(self.bv.start) == 0x43434343
- w.write64(0x4444444444444444, self.bv.start)
- assert r.read64(self.bv.start) == 0x4444444444444444
- assert self.bv.read_int(self.bv.start, 8, False, Endianness.LittleEndian) == 0x4444444444444444
- assert self.bv.read_pointer(self.bv.start) == 0x44444444
-
- value = b'\x45\x46\x47\x48'
- self.bv[self.bv.start + 0: self.bv.start + 4] = value
- assert self.bv[self.bv.start + 0: self.bv.start + 4] == value
- self.assertRaises(IndexError, lambda: self.bv[0:4:2])
- assert self.bv[self.bv.start + 4: self.bv.start + 0] == b""
- self.bv[-len(self.bv)] = b'\x01'
- assert self.bv[-len(self.bv)] == b'\x01'
-
- w.write16le(0x4142, self.bv.start)
- assert r.read16le(self.bv.start) == 0x4142
- w.write32le(0x43444546, self.bv.start)
- assert r.read32le(self.bv.start) == 0x43444546
- w.write64le(0x4748494a4b4c4d4e, self.bv.start)
- assert r.read64le(self.bv.start) == 0x4748494a4b4c4d4e
-
- w.write16be(0x4142, self.bv.start)
- assert r.read16be(self.bv.start) == 0x4142
- w.write32be(0x43444546, self.bv.start)
- assert r.read32be(self.bv.start) == 0x43444546
- w.write64be(0x4748494a4b4c4d4e, self.bv.start)
- assert r.read64be(self.bv.start) == 0x4748494a4b4c4d4e
-
- assert w.endianness == Endianness.LittleEndian
- w.endianness = Endianness.BigEndian
- assert r.endianness == Endianness.BigEndian
-
- w.write8(0x41, self.bv.start)
- assert r.read8(self.bv.start) == 0x41
- w.write16(0x4242, self.bv.start)
- assert r.read16be(self.bv.start) == 0x4242
- w.write32(0x43434343, self.bv.start)
- assert r.read32be(self.bv.start) == 0x43434343
- w.write64(0x4444444444444444, self.bv.start)
- assert r.read64be(self.bv.start) == 0x4444444444444444
-
- w.write16le(0x4142, self.bv.start)
- assert r.read16le(self.bv.start) == 0x4142
- w.write32le(0x43444546, self.bv.start)
- assert r.read32le(self.bv.start) == 0x43444546
- w.write64le(0x4748494a4b4c4d4e, self.bv.start)
- assert r.read64le(self.bv.start) == 0x4748494a4b4c4d4e
-
- w.write16be(0x4142, self.bv.start)
- assert r.read16be(self.bv.start) == 0x4142
- w.write32be(0x43444546, self.bv.start)
- assert r.read32be(self.bv.start) == 0x43444546
- w.write64be(0x4748494a4b4c4d4e, self.bv.start)
- assert r.read64be(self.bv.start) == 0x4748494a4b4c4d4e
-
- reloc_start = self.bv.relocation_ranges[0][0]
- self.assertRaises(RelocationWriteException, lambda: w.write(b'1', reloc_start, except_on_relocation=True))
- self.assertRaises(RelocationWriteException, lambda: w.write8(1, reloc_start, except_on_relocation=True))
- self.assertRaises(RelocationWriteException, lambda: w.write16(1, reloc_start, except_on_relocation=True))
- self.assertRaises(RelocationWriteException, lambda: w.write32(1, reloc_start, except_on_relocation=True))
- self.assertRaises(RelocationWriteException, lambda: w.write64(1, reloc_start, except_on_relocation=True))
-
- # Ensure these don't raise
- w.write(b'1', reloc_start, except_on_relocation=False)
- w.write8(1, reloc_start, except_on_relocation=False)
- w.write16(1, reloc_start, except_on_relocation=False)
- w.write32(1, reloc_start, except_on_relocation=False)
- w.write64(1, reloc_start, except_on_relocation=False)
-
- assert self.bv.modified
-
- def test_parse_expression(self):
- assert self.bv.eval("0x10 + 0x10") == 0x20
- self.assertRaises(ValueError, lambda: self.bv.eval("asdflkja + wlekjlxkj"))
-
- def test_load_settings_type_names(self):
- assert self.bv.get_load_settings_type_names() == []
-
- def test_bv_comments(self):
- self.bv.set_comment_at(self.bv.start, "This is a comment")
- assert self.bv.get_comment_at(self.bv.start) == "This is a comment"
- assert self.bv.address_comments == {self.bv.start : "This is a comment"}
-
- def test_bv_sections(self):
- assert self.bv.get_unique_section_names(['foo', 'foo']) == ["foo", "foo#1"]
- sec = self.bv.get_section_by_name('.ARM.exidx')
- assert sec.name == '.ARM.exidx'
- assert self.bv.get_section_by_name("Not a section") is None
- assert self.bv.get_sections_at(sec.start)[0].name == sec.name
- self.bv.add_user_section("foo", sec.start, len(sec))
- assert "foo" in [s.name for s in self.bv.get_sections_at(sec.start)]
- self.bv.remove_user_section("foo")
- assert "foo" not in [s.name for s in self.bv.get_sections_at(sec.start)]
-
- self.bv.add_auto_section("foo", sec.start, len(sec))
- assert "foo" in [s.name for s in self.bv.get_sections_at(sec.start)]
- self.bv.remove_auto_section("foo")
- assert "foo" not in [s.name for s in self.bv.get_sections_at(sec.start)]
-
- def test_get_data_offset_for_address(self):
- assert self.bv.get_data_offset_for_address(self.bv.start) == 0
- assert self.bv.get_data_offset_for_address(-1) is None
- assert self.bv.get_address_for_data_offset(0) == self.bv.start
- assert self.bv.get_address_for_data_offset(-1) is None
-
- def test_bv_segments(self):
- seg_start = self.bv.end
- seg_len = 0x1000
- orig_seg_count = len(self.bv.segments)
- assert self.bv.get_segment_at(-1) is None
- self.bv.add_user_segment(seg_start, seg_len, 0, 0, SegmentFlag.SegmentReadable)
- seg = self.bv.get_segment_at(seg_start)
- assert orig_seg_count + 1 == len(self.bv.segments)
- assert seg.start == seg_start
- assert seg.end == seg_start + seg_len
- assert seg.data_offset == 0
- assert seg.data_length == 0
- assert seg.readable and not seg.writable and not seg.executable
- assert self.bv.end == seg_start + seg_len
- self.bv.remove_user_segment(seg_start, seg_len)
- assert self.bv.end == seg_start
- assert orig_seg_count == len(self.bv.segments)
-
-
- self.bv.add_auto_segment(seg_start, seg_len, 0, 0, SegmentFlag.SegmentReadable)
- seg = self.bv.get_segment_at(seg_start)
- assert orig_seg_count + 1 == len(self.bv.segments)
- assert seg.start == seg_start
- assert seg.end == seg_start + seg_len
- assert seg.data_offset == 0
- assert seg.data_length == 0
- assert seg.readable and not seg.writable and not seg.executable
- assert self.bv.end == seg_start + seg_len
- self.bv.remove_auto_segment(seg_start, seg_len)
- assert self.bv.end == seg_start
- assert orig_seg_count == len(self.bv.segments)
-
-
- def test_rebase(self):
- rebase_addr = self.bv.start + 0x1000
- rebased_bv = self.bv.rebase(rebase_addr)
- assert rebased_bv.start == rebase_addr
-
- # TODO: Figure out why this code doesn't work
- # called_back = False
- # def progress(cur, total):
- # global called_back
- # called_back = True
- # return True
- # bv2 = self.bv.rebase(self.bv.start + 0x1000, True, progress)
- # bv2.update_analysis_and_wait()
- # assert called_back
-
- def test_reanalyze(self):
- assert self.bv.reanalyze() is None
-
- def test_properties(self):
- assert not self.bv.parse_only
- limit = self.bv.preload_limit
- assert isinstance(limit, int)
- self.bv.preload_limit = 10
- assert self.bv.preload_limit == 10
- self.bv.preload_limit = limit
- assert self.bv.parent_view.parent_view is None
- assert not self.bv.has_database
- assert self.bv.view == 'Hex:Raw'
- self.bv.view = 'Linear:ELF'
- assert self.bv.view == 'Hex:Raw' # Apparently these aren't settable from a headless script
- assert self.bv.offset == 0
- self.bv.offset = self.bv.start + 8
- assert self.bv.offset == 0 # Apparently these aren't settable from a headless script
- assert not self.bv.relocatable
- assert self.bv.executable
- assert self.bv.has_functions
- assert self.bv.has_data_variables
- assert self.bv.saved # TODO I assume this API is broken as it returns true even when not the file hasn't been saved
- assert self.bv.has_symbols
- assert self.bv.type_names[0] == 'Elf32_Dyn'
- assert self.bv.global_pointer_value.type == RegisterValueType.UndeterminedValue
-
- def test_blocks(self):
- assert isinstance(next(self.bv.basic_blocks), BasicBlock)
- assert isinstance(next(self.bv.llil_basic_blocks), LowLevelILBasicBlock)
- assert isinstance(next(self.bv.mlil_basic_blocks), MediumLevelILBasicBlock)
- assert isinstance(next(self.bv.hlil_basic_blocks), HighLevelILBasicBlock)
- tokens, addr = next(self.bv.instructions)
- assert isinstance(addr, int)
- assert isinstance(tokens[0], InstructionTextToken)
-
- def test_instructions(self):
- assert isinstance(next(self.bv.llil_instructions), LowLevelILInstruction)
- assert isinstance(next(self.bv.mlil_instructions), MediumLevelILInstruction)
- assert isinstance(next(self.bv.hlil_instructions), HighLevelILInstruction)
-
- def test_functions(self):
- assert isinstance(next(self.bv.mlil_functions()), MediumLevelILFunction)
- assert isinstance(next(self.bv.hlil_functions()), HighLevelILFunction)
-
- def test_define_types(self):
- self.bv.define_user_type("foo", "int")
- self.bv.define_user_type(None, type_obj="int bas")
- self.assertRaises(SyntaxError, lambda:self.bv.define_user_type(None, type_obj="a"))
- assert self.bv.get_type_by_name("foo") == Type.int(4, True)
- assert self.bv.get_type_by_name("bas") == Type.int(4, True)
- self.bv.rename_type("foo", "bar")
- assert self.bv.get_type_by_name("bar") == Type.int(4, True)
- self.bv.undefine_user_type("bar")
- assert self.bv.get_type_by_name("bar") is None
-
- type_id = "some unique string"
- type_name = "some name"
- self.bv.define_type(type_id, type_name, "int")
- assert self.bv.get_type_by_name(type_name) == Type.int(4, True)
- assert self.bv.is_type_auto_defined(type_name)
- t = self.bv.get_type_by_name(type_name)
- assert type_id == self.bv.get_type_id(type_name)
- assert self.bv.get_type_name_by_id(type_id) == type_name
-
- def test_type_libraries(self):
- tl = self.bv.get_type_library('libc_armv7.so.6')
- assert tl.name == 'libc_armv7.so.6'
- assert self.bv.get_type_library('not a type library') is None
- self.assertRaises(ValueError, lambda: self.bv.add_type_library("asdf"))
- self.bv.add_type_library(tl)
- assert self.bv.type_libraries[0].name == tl.name
-
- def test_parse_types(self):
- source = r"""
- int foo;
- struct baz { int x; int y; };
- int bar(int bas) { return bas; }
- """
- result = self.bv.parse_types_from_string(source)
- assert result.variables["foo"] == Type.int(4)
- s = result.types["baz"]
- s2 = Type.structure([(Type.int(4), "x"), (Type.int(4), "y")])
- assert s.members == s2.members
- a = Type.function(Type.int(4), [("bas", Type.int(4))], calling_convention=self.bv.platform.default_calling_convention)
- b = result.functions["bar"]
- assert a.calling_convention == b.calling_convention
- assert a.return_value == b.return_value
- assert a.parameters == b.parameters
-
- self.assertRaises(ValueError, lambda: self.bv.parse_type_string(None))
- self.assertRaises(SyntaxError, lambda: self.bv.parse_type_string("a"))
- self.assertRaises(ValueError, lambda: self.bv.parse_types_from_string(None))
- self.assertRaises(SyntaxError, lambda: self.bv.parse_types_from_string("a"))
-
- def test_disassembly_tokens(self):
- address = self.bv.get_symbols_by_name("main")[0].address
- tokens, size = next(self.bv.disassembly_tokens(address))
- assert size == 4
- assert str(tokens[0]) == "push"
- string, size = next(self.bv.disassembly_text(address))
- assert size == 4
- assert string.startswith("push")
- assert self.bv.get_disassembly(address).startswith("push")
-
- def test_is_offset_x(self):
- writable_addr = 0x00010f0c
- sec_addr = self.bv.sections['.text'].start
- extern_seg = self.bv.segments[-1].start
- writable_semantics = 0x00011028
- assert self.bv.is_valid_offset(self.bv.start)
- assert not self.bv.is_valid_offset(self.bv.end)
-
- assert self.bv.is_offset_readable(self.bv.start)
- assert not self.bv.is_offset_readable(self.bv.end)
-
- assert self.bv.is_offset_writable(writable_addr)
- assert not self.bv.is_offset_writable(self.bv.start)
-
- assert self.bv.is_offset_executable(self.bv.start)
- assert not self.bv.is_offset_executable(extern_seg)
-
- assert self.bv.is_offset_code_semantics(sec_addr)
- assert not self.bv.is_offset_code_semantics(0x00008154)
-
- assert self.bv.is_offset_extern_semantics(extern_seg)
- assert not self.bv.is_offset_extern_semantics(self.bv.start)
-
- assert self.bv.is_offset_writable_semantics(writable_semantics)
- assert not self.bv.is_offset_writable_semantics(extern_seg)
-
-
-class TestBinaryViewType(unittest.TestCase):
- def test_binaryviewtype(self):
- self.assertRaises(KeyError, lambda: bn.BinaryViewType['not_a_binary_view'])
- bvt = BinaryViewType["PE"]
- bvt2 = BinaryViewType["ELF"]
- assert repr(bvt) == "<view type: 'PE'>"
- assert bvt == bvt
- assert bvt != bvt2
- assert hash(bvt) != hash(bvt2)
- assert bvt.name == "PE"
- assert bvt.long_name == "PE"
- assert not bvt.is_deprecated
- assert bvt2.get_arch(3, Endianness.LittleEndian) == Architecture["x86"]
- assert bvt2.get_platform(0, Architecture["x86"]) == Platform["linux-x86"]
- with FileApparatus("helloworld") as filename:
- with bn.load(filename) as bv:
- assert bvt2.is_valid_for_data(bv.parent_view)
- assert isinstance(bvt2.parse(bv.parent_view), BinaryView)
-
-
-class TestArchitecture(TestWithBinaryView):
- def test_available_patches_x86(self):
- x86 = binaryninja.Architecture["x86"]
-
- je_0 = x86.assemble("je 0")
- call_0 = x86.assemble("call 0")
- jmp_eax = x86.assemble("jmp eax")
-
- assert x86.is_never_branch_patch_available(je_0, 0) == True
- assert x86.is_never_branch_patch_available(call_0, 0) == False
-
- assert x86.is_always_branch_patch_available(je_0, 0) == True
- assert x86.is_always_branch_patch_available(call_0, 0) == False
-
- assert x86.is_invert_branch_patch_available(je_0, 0) == True
- assert x86.is_invert_branch_patch_available(call_0, 0) == False
-
- assert x86.is_skip_and_return_zero_patch_available(call_0, 0) == True
- assert x86.is_skip_and_return_zero_patch_available(jmp_eax, 0) == False
-
- assert x86.is_skip_and_return_value_patch_available(call_0, 0) == True
- assert x86.is_skip_and_return_value_patch_available(jmp_eax, 0) == False
-
- assert x86.convert_to_nop(je_0, 0) == b'\x90\x90\x90\x90\x90\x90'
- assert x86.always_branch(je_0, 0) == b'\x90\xe9\xfa\xff\xff\xff'
- assert x86.invert_branch(je_0, 0) == b'\x0f\x85\xfa\xff\xff\xff'
- assert x86.skip_and_return_value(je_0, 0, 0) == b'\xb8\x00\x00\x00\x00\x90'
-
- def test_available_typelibs(self):
- assert len(self.bv.arch.type_libraries) > 0
-
-
-class LowLevelILTests(TestWithBinaryView):
- def setUp(self):
- super().setUp()
- self.assertEqual(self.bv.arch.name, Architecture['armv7'].name, "hello-world is not armv7?")
- self.func = self.bv.get_functions_by_name("main")[0]
- self.llil = self.func.low_level_il
-
- def assertIsOptionalInstance(self, item, optional_type):
- assert (isinstance(item, optional_type) or item is None)
-
- def test_dataclasses(self):
- llil_label = LowLevelILLabel()
- self.assertIsNotNone(llil_label.handle)
-
- sem_flag_class = ILSemanticFlagClass(Architecture['aarch64'], 1)
- self.assertIsInstance(sem_flag_class.__str__(), str)
- self.assertEqual(sem_flag_class.__str__(), sem_flag_class.name)
- self.assertIsInstance(sem_flag_class.__repr__(), str)
- self.assertIsInstance(sem_flag_class.__int__(), int)
-
- sem_flag_group = ILSemanticFlagGroup(Architecture['aarch64'], 1)
- self.assertIsInstance(sem_flag_group.__str__(), str)
- self.assertEqual(sem_flag_group.__str__(), sem_flag_group.name)
- self.assertIsInstance(sem_flag_group.__repr__(), str)
- self.assertIsInstance(sem_flag_group.__int__(), int)
-
- intrinsic = ILIntrinsic(Architecture['aarch64'], 0)
- self.assertIsInstance(intrinsic.__str__(), str)
- self.assertIsInstance(intrinsic.__repr__(), str)
- self.assertIsInstance(intrinsic.name, str)
-
- func = LowLevelILFunction(arch=Architecture['aarch64'])
- const = func.const(8, 0x1111)
- func.append(const)
- const = func.const(8, 0x2222)
- func.append(const)
- const = func.const(8, 0x1111)
- func.append(const)
- func.finalize()
-
- const_1 = func.basic_blocks[0].disassembly_text[0].il_instruction
- const_2 = func.basic_blocks[0].disassembly_text[1].il_instruction
- const_3 = func.basic_blocks[0].disassembly_text[2].il_instruction
-
- self.assertTrue(const_1)
- self.assertEqual(int(const_1), 0x1111)
- self.assertEqual(const_1, const_3)
- self.assertNotEqual(const_1, const_2)
- self.assertLess(const_1, const_2)
- self.assertLessEqual(const_1, const_3)
- self.assertGreater(const_2, const_1)
- self.assertGreaterEqual(const_1, const_3)
- self.assertIsInstance(const_1.__hash__(), int)
-
- def test_ILRegister(self):
- x86_reg_0 = ILRegister(arch=Architecture['x86'], index=RegisterIndex(0))
- x86_reg_0_dup = ILRegister(arch=Architecture['x86'], index=RegisterIndex(0))
- x86_reg_1 = ILRegister(arch=Architecture['x86'], index=RegisterIndex(1))
- arm_reg_0 = ILRegister(arch=Architecture['armv7'], index=RegisterIndex(0))
- arm_reg_1 = ILRegister(arch=Architecture['armv7'], index=RegisterIndex(1))
- arm_reg_bad = ILRegister(arch=Architecture['armv7'], index=None)
-
- self.assertEqual(x86_reg_0.index, int(x86_reg_0))
-
- self.assertEqual(x86_reg_0, x86_reg_0_dup, "Register equality not properly implemented")
- self.assertNotEqual(x86_reg_0, x86_reg_1, "Register inequality not properly implemented")
- self.assertNotEqual(x86_reg_0, arm_reg_0, "Register inequality not properly implemented")
- self.assertEqual(arm_reg_0, "r0", "Register equality when 'other' is a string not properly implemented")
- self.assertEqual(arm_reg_0.__eq__(["definitely", "not", "a", "reg", "or", "string"]), NotImplemented)
- self.assertEqual(arm_reg_0.name, 'r0', "Passthrough of arm register zero name is incorrect")
-
- self.assertEqual(arm_reg_0.info.index, 0, "Register Info Index is incorrect")
- self.assertEqual(arm_reg_1.info.index, 1, "Register Info Index is incorrect")
-
- def test_LLILInstruction(self):
- create_instr = LowLevelILInstruction.create(self.func.low_level_il, 1)
-
- self.assertIsNotNone(create_instr)
-
- instrs = list(self.llil.instructions)
- instr = list(self.llil.instructions)[1]
- self.assertEqual(instr.__eq__("not_a_llil_instruction"), NotImplemented)
- self.assertEqual(instr.__ne__("not_a_llil_instruction"), NotImplemented)
- self.assertEqual(instr.__lt__("not_a_llil_instruction"), NotImplemented)
- self.assertEqual(instr.__le__("not_a_llil_instruction"), NotImplemented)
- self.assertEqual(instr.__gt__("not_a_llil_instruction"), NotImplemented)
- self.assertEqual(instr.__ge__("not_a_llil_instruction"), NotImplemented)
-
- self.assertEqual(instr, instrs[1])
- self.assertNotEqual(instr, instrs[0])
-
- self.assertLess(instr, instrs[2])
- self.assertLessEqual(instr, instrs[1])
-
- self.assertGreater(instr, instrs[0])
- self.assertGreaterEqual(instr, instrs[1])
-
- self.assertNotEqual(hash(instr), 0)
-
- self.assertEqual(instr.size, 4) # armv7, all ins are length 4
-
- self.assertEqual(instr.operation, LowLevelILOperation.LLIL_PUSH)
-
- self.assertGreater(instr.il_basic_block.length, 0)
- self.assertIsNotNone(instr.il_basic_block.source_block)
-
- self.assertIsNotNone(instr.mmlil)
-
- pv = instr.get_possible_values()
- self.assertIsNotNone(pv)
- self.assertIsInstance(pv, PossibleValueSet)
-
- rv = instr.get_reg_value(RegisterIndex(0))
- self.assertIsInstance(rv, RegisterValue)
-
- rva = instr.get_reg_value_after(RegisterIndex(0))
- self.assertIsInstance(rva, RegisterValue)
-
- prv = instr.get_possible_reg_values(RegisterIndex(0))
- self.assertIsNotNone(prv)
- self.assertIsInstance(prv, PossibleValueSet)
-
- prva = instr.get_possible_reg_values_after(RegisterIndex(0))
- self.assertIsNotNone(prva)
- self.assertIsInstance(prva, PossibleValueSet)
-
- reg_ssa_list = instr._get_reg_ssa_list(0)
- self.assertIsInstance(reg_ssa_list, list)
- for item in reg_ssa_list:
- self.assertIsInstance(item, SSARegister)
-
- reg_stack_ssa_list = instr._get_reg_stack_ssa_list(0)
- self.assertIsInstance(reg_stack_ssa_list, list)
- for item in reg_stack_ssa_list:
- self.assertIsInstance(item, SSARegisterStack)
-
- flag_ssa_list = instr._get_flag_ssa_list(0)
- self.assertIsInstance(flag_ssa_list, list)
- for item in flag_ssa_list:
- self.assertIsInstance(item, SSAFlag)
-
- reg_or_flag_ssa_list = instr._get_reg_or_flag_ssa_list(0)
- self.assertIsInstance(reg_or_flag_ssa_list, list)
- for item in reg_or_flag_ssa_list:
- self.assertIsInstance(item, SSARegisterOrFlag)
-
- def test_LLILFunction(self):
- arch = self.bv.arch
- source_func = self.func
-
- # func_no_handle = LowLevelILFunction(arch=arch, handle=None, source_func=source_func)
- func_no_source_func = LowLevelILFunction(arch=arch, handle=core.BNCreateLowLevelILFunction(arch.handle, self.func.handle), source_func=None)
- # func_no_arch = LowLevelILFunction(arch=None, handle=core.BNCreateLowLevelILFunction(arch.handle, self.func.handle), source_func=source_func)
-
- assert len(list(self.func.llil_instructions)) != 0
- assert len(self.llil) == len(list(self.llil.instructions))
-
- self.assertRaises(Exception, lambda: LowLevelILFunction())
-
- ins_count: ExpressionIndex = len(self.llil)
- self.assertRaises(IndexError, lambda: self.llil[1:3])
- self.assertRaises(IndexError, lambda: self.llil[ins_count])
- self.assertRaises(IndexError, lambda: self.llil[(-ins_count) - 1])
- self.assertEqual(self.llil[ins_count-1], self.llil[-1])
- self.assertRaises(IndexError, lambda: self.llil.__setitem__('a', 'b'))
-
- addr = self.llil.current_address
- self.assertIsInstance(addr, int)
- self.llil.current_address = addr + 8
- self.assertEqual(self.llil.current_address, addr + 8)
- self.llil.current_address = addr
-
- self.llil.set_current_address(addr + 16, arch=None)
- self.assertEqual(self.llil.current_address, addr + 16)
- self.llil.current_address = addr
- self.llil.set_current_address(addr + 32)
- self.assertEqual(self.llil.current_address, addr + 32)
-
- self.assertIsInstance(self.llil.temp_reg_count, int)
- self.assertIsInstance(self.llil.temp_flag_count, int)
-
- self.assertIsInstance(self.llil.mlil, MediumLevelILFunction)
- self.assertIsInstance(self.llil.mapped_medium_level_il, MediumLevelILFunction)
-
- self.assertEqual(self.llil.mmlil, self.llil.mapped_medium_level_il)
-
- self.llil.arch = Architecture['x86_64']
- self.assertEqual(self.llil.arch, Architecture['x86_64'])
- self.llil.arch = Architecture['armv7']
-
- self.llil.source_function = None
- self.assertIsNone(self.llil.source_function)
- self.llil.source_function = self.func
-
- ssa_rs = self.llil.ssa_register_stacks
- self.assertIsInstance(ssa_rs, list)
- for reg_stack in ssa_rs:
- self.assertIsInstance(reg_stack, SSARegisterStack)
-
- ssa_flags = self.llil.ssa_flags
- self.assertIsInstance(ssa_flags, list)
- for flag in ssa_flags:
- self.assertIsInstance(flag, SSAFlag)
-
- mem_versions = self.llil.memory_versions
- self.assertIsInstance(mem_versions, list)
- for value in mem_versions:
- self.assertIsInstance(value, int)
-
- self.llil.source_function = None
- self.assertEqual(self.llil.vars, [])
- self.llil.source_function = self.func
-
- instruction_index = 0
- addr = list(self.llil.instructions)[instruction_index].address
- self.assertEqual(self.llil.get_instruction_start(addr), instruction_index)
- self.assertEqual(self.llil.get_instruction_start(addr, arch=None), instruction_index)
-
- expr_index = self.llil.intrinsic([34], 'SetExclusiveMonitors', [0, 1])
- self.assertIsInstance(expr_index, int)
-
- self.llil.append(self.llil.nop())
-
- self.llil.add_label_for_address(self.func.arch, addr)
- self.assertIsInstance(self.llil.get_label_for_address(self.func.arch, addr), LowLevelILLabel)
-
- index = self.llil.get_high_level_il_instruction_index(InstructionIndex(0))
- self.assertIsOptionalInstance(index, int)
-
- index = self.llil.get_high_level_il_expr_index(0)
- self.assertIsOptionalInstance(index, int)
-
- new_func = LowLevelILFunction(arch=Architecture['aarch64'])
-
- self.assertEqual(new_func.il_form, FunctionGraphType.InvalidILViewType)
- self.assertEqual(new_func.ssa_registers, [])
- self.assertEqual(new_func.vars, [])
-
- def do_il_expression_test(self, target_function, prefix_args, llil_instruction_type, const_args=0, suffix_args=None):
- """
- Helper function for testing LowLevelILFunction Expression generators
- Without this function, the next block of code takes up almost half of this file.
-
- :param target_function: Target function to test
- :param prefix_args: Arguments before we pass the const expressions as arguments
- :param llil_instruction_type: LowLevelILInstruction type this function should append to the LLILFunc
- :param const_args: int amount of const expressions we need to create and pass as arguments.
- :param suffix_args: Argumemts after we pass the const expressions as arguments
- :return: ILInstruction instance that was appended.
- """
- if suffix_args is None:
- suffix_args = []
-
- func = LowLevelILFunction(arch=Architecture['aarch64'])
- function_args = [func] + prefix_args
- const_val = 0
-
- const = func.const(8, const_val)
- func.append(const)
-
- target_expr_index = 1
- for i in range(const_args):
- const = func.const(8, const_val)
- const_val += 8
- func.append(const)
- function_args.append(const)
- target_expr_index += 1
-
- function_args += suffix_args
-
- expression = target_function(*function_args)
-
- func.append(expression)
- func.finalize()
-
- self.assertEqual(func.basic_blocks[0].disassembly_text[target_expr_index].il_instruction.__class__, llil_instruction_type,
- f"LowLevelILFunction.{target_function.__name__} didn't append expected "
- f"{llil_instruction_type.__name__} instruction")
-
- return func.basic_blocks[0].disassembly_text[target_expr_index].il_instruction
-
- def test_individual_expressions(self):
-
- with self.assertRaises(AssertionError, msg="do_il_expression_test not failing properly."):
- self.do_il_expression_test(LowLevelILFunction.nop, prefix_args=[], llil_instruction_type=LowLevelILConst)
-
- """
- The function this method primarily uses has a docstring explaining it, but essentially, pass the function attribute,
- args as a list, the class we should verify it matches,
- however many consts you need to create and inject into the args,
- and then any args that come after the consts.
-
- It will verify it appends the proper ILInstruction subclass, then will return that ILInstruction, in the event
- you need to do any further testing.
- """
-
- self.do_il_expression_test(target_function=LowLevelILFunction.nop, prefix_args=[], llil_instruction_type=LowLevelILNop)
- self.do_il_expression_test(LowLevelILFunction.const, [8, 0x1234], LowLevelILConst)
- self.do_il_expression_test(LowLevelILFunction.set_reg, [8, RegisterName('x0')], LowLevelILSetReg, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.set_reg_stack_top_relative, [8, 0, 0, 0], LowLevelILSetRegStackRel)
- self.do_il_expression_test(LowLevelILFunction.reg_stack_push, [8, 0, 0], LowLevelILRegStackPush)
- self.do_il_expression_test(LowLevelILFunction.load, [8, 0], LowLevelILLoad)
- self.do_il_expression_test(LowLevelILFunction.store, [8, 0, 0x8], LowLevelILStore)
- self.do_il_expression_test(LowLevelILFunction.push, [8, 0x0], LowLevelILPush)
- self.do_il_expression_test(LowLevelILFunction.pop, [8], LowLevelILPop)
- self.do_il_expression_test(LowLevelILFunction.reg, [8, 'x0'], LowLevelILReg)
- self.do_il_expression_test(LowLevelILFunction.reg_split, [16, 'x3', 'x4'], LowLevelILRegSplit)
- self.do_il_expression_test(LowLevelILFunction.reg_stack_top_relative, [4, 0, 0], LowLevelILRegStackRel)
- self.do_il_expression_test(LowLevelILFunction.reg_stack_push, [8, 0, 0x4], LowLevelILRegStackPush)
- self.do_il_expression_test(LowLevelILFunction.reg_stack_pop, [8, 0], LowLevelILRegStackPop)
- self.do_il_expression_test(LowLevelILFunction.const_pointer, [8, 0x100000000], LowLevelILConstPtr)
- self.do_il_expression_test(LowLevelILFunction.reloc_pointer, [8, 0x100000000], LowLevelILExternPtr)
- self.do_il_expression_test(LowLevelILFunction.float_const_raw, [8, 0x4141414141414141], LowLevelILFloatConst)
- self.do_il_expression_test(LowLevelILFunction.float_const_single, [12345.678], LowLevelILFloatConst)
- self.do_il_expression_test(LowLevelILFunction.float_const_double, [12345.678], LowLevelILFloatConst)
- self.do_il_expression_test(LowLevelILFunction.undefined, [], LowLevelILUndef)
- self.do_il_expression_test(LowLevelILFunction.breakpoint, [], LowLevelILBp)
- self.do_il_expression_test(LowLevelILFunction.trap, [0], LowLevelILTrap)
- self.do_il_expression_test(LowLevelILFunction.add, [8], LowLevelILAdd, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.add_carry, [8], LowLevelILAdc, const_args=3)
- self.do_il_expression_test(LowLevelILFunction.sub, [8], LowLevelILSub, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.sub_borrow, [8], LowLevelILSbb, const_args=3)
- self.do_il_expression_test(LowLevelILFunction.and_expr, [8], LowLevelILAnd, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.or_expr, [8], LowLevelILOr, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.xor_expr, [8], LowLevelILXor, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.shift_left, [8], LowLevelILLsl, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.logical_shift_right, [8], LowLevelILLsr, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.arith_shift_right, [8], LowLevelILAsr, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.shift_left, [8], LowLevelILLsl, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.rotate_left, [8], LowLevelILRol, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.rotate_left_carry, [8], LowLevelILRlc, const_args=3)
- self.do_il_expression_test(LowLevelILFunction.rotate_right_carry, [8], LowLevelILRrc, const_args=3)
- self.do_il_expression_test(LowLevelILFunction.rotate_right, [8], LowLevelILRor, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mult, [8], LowLevelILMul, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mult_double_prec_signed, [8], LowLevelILMulsDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mult_double_prec_unsigned, [8], LowLevelILMuluDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.div_signed, [8], LowLevelILDivs, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.div_double_prec_signed, [8], LowLevelILDivsDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.div_unsigned, [8], LowLevelILDivu, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.div_double_prec_unsigned, [8], LowLevelILDivuDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mod_signed, [8], LowLevelILMods, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mod_double_prec_signed, [8], LowLevelILModsDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mod_unsigned, [8], LowLevelILModu, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.mod_double_prec_unsigned, [8], LowLevelILModuDp, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.neg_expr, [8], LowLevelILNeg, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.not_expr, [8], LowLevelILNot, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.sign_extend, [8], LowLevelILSx, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.zero_extend, [8], LowLevelILZx, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.low_part, [8], LowLevelILLowPart, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.jump, [], LowLevelILJump, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.call, [], LowLevelILCall, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.tailcall, [], LowLevelILTailcall, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.ret, [], LowLevelILRet, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.no_ret, [], LowLevelILNoret)
- self.do_il_expression_test(LowLevelILFunction.compare_equal, [8], LowLevelILCmpE, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_not_equal, [8], LowLevelILCmpNe, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_signed_less_than, [8], LowLevelILCmpSlt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_unsigned_less_than, [8], LowLevelILCmpUlt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_signed_less_equal, [8], LowLevelILCmpSle, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_unsigned_less_equal, [8], LowLevelILCmpUle, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_signed_greater_than, [8], LowLevelILCmpSgt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_unsigned_greater_than, [8], LowLevelILCmpUgt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_signed_greater_equal, [8], LowLevelILCmpSge, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.compare_unsigned_greater_equal, [8], LowLevelILCmpUge, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.test_bit, [8], LowLevelILTestBit, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.system_call, [], LowLevelILSyscall)
- self.do_il_expression_test(LowLevelILFunction.unimplemented, [], LowLevelILUnimpl)
- self.do_il_expression_test(LowLevelILFunction.unimplemented_memory_ref, [8], LowLevelILUnimplMem, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_add, [8], LowLevelILFadd, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_sub, [8], LowLevelILFsub, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_mult, [8], LowLevelILFmul, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_div, [8], LowLevelILFdiv, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_sqrt, [8], LowLevelILFsqrt, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_neg, [8], LowLevelILFneg, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_to_int, [8], LowLevelILFloatToInt, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.int_to_float, [8], LowLevelILIntToFloat, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_convert, [8], LowLevelILFloatConv, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.round_to_int, [8], LowLevelILRoundToInt, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.floor, [8], LowLevelILFloor, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.ceil, [8], LowLevelILCeil, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_trunc, [8], LowLevelILFtrunc, const_args=1)
- self.do_il_expression_test(LowLevelILFunction.float_compare_equal, [8], LowLevelILFcmpE, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_not_equal, [8], LowLevelILFcmpNe, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_less_than, [8], LowLevelILFcmpLt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_less_equal, [8], LowLevelILFcmpLe, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_greater_than, [8], LowLevelILFcmpGt, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_greater_equal, [8], LowLevelILFcmpGe, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_ordered, [8], LowLevelILFcmpO, const_args=2)
- self.do_il_expression_test(LowLevelILFunction.float_compare_unordered, [8], LowLevelILFcmpUo, const_args=2)
-
-
-# class TestObjectiveCPlugin(unittest.TestCase):
-# def setUp(self):
-# with FileApparatus("calculator_macOS12_arm64e") as path:
-# bv = load(
-# os.path.relpath(path),
-# options={"workflows.enable": True, "workflows.functionWorkflow": "core.function.objectiveC"}
-# )
-# bv.update_analysis_and_wait()
-
-# self.bv: BinaryView = bv
-# self.arch: Architecture = self.bv.arch
-# self.plat: Platform = self.bv.platform
-
-# def test_function_nat(self):
-# f = self.bv.get_function_at(0x10000667c)
-# ft = f.function_type
-
-# # Ensure return value and parameter types are being set
-# assert "CGFloat" == str(ft.return_value)
-# assert len(ft.parameters) >= 2
-# assert "SEL" in str(ft.parameters[1])
-
-# # Ensure function names are being set
-# assert "doubleValue" in f.name
-
-# def test_data_vars_created(self):
-# dv1 = self.bv.get_data_var_at(0x1000331a0)
-# dv2 = self.bv.get_data_var_at(0x10001f4b0)
-
-# # Ensure data variables are being created
-# assert "class" in str(dv1.type)
-# assert "method" in str(dv2.type)
-
-# def test_method_call_resolution(self):
-# f = self.bv.get_function_at(0x10000667c)
-# assert f
-
-# # Lazier way of checking that the method call rewriting worked
-# assert "actualValuePeriodDecimal" in str(f.hlil)
-# assert "doubleValue" in str(f.hlil)