summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2022-01-25 10:20:13 -0500
committerPeter LaFosse <peter@vector35.com>2022-01-25 10:20:26 -0500
commitf1b487d1997fbf0e03f87114dd152a7e258a88c5 (patch)
tree0d30527f1cacdab3f5a272c10e77e5793fe9e8cd
parent2c0f75b954dea781b7ac68eee0ec7e8fbeadee4e (diff)
Fix errors and add unit test for EnumBuilder
-rw-r--r--python/types.py95
-rw-r--r--suite/api_test.py57
-rw-r--r--suite/testcommon.py2
3 files changed, 88 insertions, 66 deletions
diff --git a/python/types.py b/python/types.py
index 3f832fe4..40ed41b1 100644
--- a/python/types.py
+++ b/python/types.py
@@ -633,10 +633,6 @@ class TypeBuilder:
return NamedTypeReferenceBuilder.named_type_from_type_and_id(type_id, name, type)
@staticmethod
- def generate_named_type_reference(guid:str, name:QualifiedName) -> 'NamedTypeReferenceBuilder':
- return NamedTypeReferenceBuilder.generate_named_type_reference(guid, name)
-
- @staticmethod
def named_type_from_registered_type(view:'binaryview.BinaryView', name:QualifiedName) -> 'NamedTypeReferenceBuilder':
return NamedTypeReferenceBuilder.named_type_from_registered_type(view, name)
@@ -1215,15 +1211,6 @@ class EnumerationBuilder(TypeBuilder):
super(EnumerationBuilder, self).__init__(handle, platform, confidence)
self.enum_builder_handle = enum_builder_handle
- @staticmethod
- def _enum_handle_from_members(members):
- enum_builder_handle = core.BNCreateEnumerationBuilder()
- for member in members:
- if member.value is None:
- core.BNAddEnumerationBuilderMember(enum_builder_handle, member.name)
- else:
- core.BNAddEnumerationBuilderMemberWithValue(enum_builder_handle, member.name, member.value)
-
@classmethod
def create(cls, members:Optional[List[EnumMembersType]]=None, width:Optional[int]=None,
arch:Optional['architecture.Architecture']=None, sign:BoolWithConfidenceType=False,
@@ -1240,7 +1227,7 @@ class EnumerationBuilder(TypeBuilder):
enum_builder_handle = core.BNCreateEnumerationBuilder()
assert enum_builder_handle is not None, "core.BNCreateEnumerationBuilder returned None"
- EnumerationBuilder.add_members(enum_builder_handle, members)
+ EnumerationBuilder._add_members(enum_builder_handle, members)
type_builder_handle = core.BNCreateEnumerationTypeBuilderWithBuilder(None, enum_builder_handle, _width, _sign)
assert type_builder_handle is not None, "core.BNCreateEnumerationTypeBuilderWithBuilder returned None"
return cls(type_builder_handle, enum_builder_handle, platform, confidence)
@@ -1254,17 +1241,6 @@ class EnumerationBuilder(TypeBuilder):
return EnumerationType(handle, self.platform, self.confidence)
@property
- def signed(self) -> BoolWithConfidence:
- """Whether type is signed (read/write)"""
- result = core.BNIsTypeBuilderSigned(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @signed.setter
- def signed(self, value:BoolWithConfidenceType) -> None: # type: ignore
- _value = BoolWithConfidence.get_core_struct(value)
- core.BNTypeBuilderSetSigned(self._handle, _value)
-
- @property
def members(self) -> List[EnumerationMember]:
"""Enumeration member list (read-only)"""
count = ctypes.c_ulonglong()
@@ -1280,10 +1256,12 @@ class EnumerationBuilder(TypeBuilder):
@members.setter
def members(self, members:List[EnumMembersType]) -> None: # type: ignore
- EnumerationBuilder.add_members(self.enum_builder_handle, members)
+ for i in reversed(range(len(self.members))):
+ self.remove(i)
+ EnumerationBuilder._add_members(self.enum_builder_handle, members)
@staticmethod
- def add_members(enum_builder_handle, members:List[EnumMembersType]):
+ def _add_members(enum_builder_handle, members:List[EnumMembersType]):
for i, member in enumerate(members):
value = None
if isinstance(member, Tuple):
@@ -1293,8 +1271,7 @@ class EnumerationBuilder(TypeBuilder):
value = member.value
elif isinstance(member, str):
name = member
- else:
- assert False, "Unhandled type for EnumerationMember"
+
if value is None:
core.BNAddEnumerationBuilderMember(enum_builder_handle, name)
else:
@@ -1302,10 +1279,7 @@ class EnumerationBuilder(TypeBuilder):
def append(self, name:str, value:Optional[int]=None) -> 'EnumerationBuilder':
- if value is None:
- core.BNAddEnumerationBuilderMember(self.enum_builder_handle, name)
- else:
- core.BNAddEnumerationBuilderMemberWithValue(self.enum_builder_handle, name, value)
+ EnumerationBuilder._add_members(self.enum_builder_handle, [EnumerationMember(name, value)])
return self
def remove(self, i:int) -> 'EnumerationBuilder':
@@ -1317,11 +1291,8 @@ class EnumerationBuilder(TypeBuilder):
return self
def __iter__(self) -> Generator[EnumerationMember, None, None]:
- for i, member in enumerate(self.members):
- if member.value is None:
- yield EnumerationMember(member.name, i)
- else:
- yield member
+ for member in self.members:
+ yield member
def __getitem__(self, value:Union[str, int, slice]):
if isinstance(value, str):
@@ -1336,7 +1307,7 @@ class EnumerationBuilder(TypeBuilder):
else:
raise ValueError(f"Incompatible type {type(value)} for __getitem__")
- def __setitem__(self, item, value):
+ def __setitem__(self, item:Union[str, int], value:Union[Optional[int], EnumerationMember]):
if isinstance(item, str):
for i, member in enumerate(self.members):
if member.name == item:
@@ -1344,7 +1315,7 @@ class EnumerationBuilder(TypeBuilder):
elif isinstance(item, int) and isinstance(value, EnumerationMember):
self.replace(item, value.name, value.value)
else:
- assert False, "Invalid type for Enumeration.__setitem__"
+ raise ValueError("Invalid type for Enumeration.__setitem__")
class NamedTypeReferenceBuilder(TypeBuilder):
@@ -2048,6 +2019,25 @@ class EnumerationType(IntegerType):
assert enum_handle is not None, "core.BNGetTypeEnumeration returned None"
self.enum_handle = enum_handle
+ def __del__(self):
+ if core is not None:
+ core.BNFreeEnumeration(self.enum_handle)
+
+ def __hash__(self):
+ return hash(ctypes.addressof(self.enum_handle.contents))
+
+ @property
+ def members(self):
+ """Enumeration member list (read-only)"""
+ count = ctypes.c_ulonglong()
+ members = core.BNGetEnumerationMembers(self.enum_handle, count)
+ assert members is not None, "core.BNGetEnumerationMembers returned None"
+ result = []
+ for i in range(0, count.value):
+ result.append(EnumerationMember(members[i].name, members[i].value))
+ core.BNFreeEnumerationMemberList(members, count.value)
+ return result
+
@classmethod
def create(cls, members=List[EnumMembersType], width:Optional[int]=None,
arch:Optional['architecture.Architecture']=None, sign:BoolWithConfidenceType=False,
@@ -2061,7 +2051,7 @@ class EnumerationType(IntegerType):
builder = core.BNCreateEnumerationBuilder()
assert builder is not None, "core.BNCreateEnumerationType returned None"
- EnumerationBuilder.add_members(builder, members)
+ EnumerationBuilder._add_members(builder, members)
core_enum = core.BNFinalizeEnumerationBuilder(builder)
assert core_enum is not None, "core.BNFinalizeEnumerationBuilder returned None"
core.BNFreeEnumerationBuilder(builder)
@@ -2081,29 +2071,6 @@ class EnumerationType(IntegerType):
assert enumeration_builder_handle is not None, "core.BNCreateEnumerationTypeBuilder returned None"
return EnumerationBuilder(type_builder_handle, enumeration_builder_handle, self.platform, self.confidence)
- def __del__(self):
- if core is not None:
- core.BNFreeEnumeration(self.enum_handle)
-
- # def __repr__(self):
- # return "<enum: %s>" % repr(self.members)
-
-
- def __hash__(self):
- return hash(ctypes.addressof(self.enum_handle.contents))
-
- @property
- def members(self):
- """Enumeration member list (read-only)"""
- count = ctypes.c_ulonglong()
- members = core.BNGetEnumerationMembers(self.enum_handle, count)
- assert members is not None, "core.BNGetEnumerationMembers returned None"
- result = []
- for i in range(0, count.value):
- result.append(EnumerationMember(members[i].name, members[i].value))
- core.BNFreeEnumerationMemberList(members, count.value)
- return result
-
def generate_named_type_reference(self, guid:str, name:QualifiedName):
ntr_type = NamedTypeReferenceClass.EnumNamedTypeClass
return NamedTypeReferenceType.create(ntr_type, guid, name,
diff --git a/suite/api_test.py b/suite/api_test.py
index 0a5770a7..44d6cd88 100644
--- a/suite/api_test.py
+++ b/suite/api_test.py
@@ -11,7 +11,7 @@ from binaryninja.pluginmanager import RepositoryManager
from binaryninja.platform import Platform
from binaryninja.function import Function
from binaryninja.enums import (StructureVariant, NamedTypeReferenceClass)
-from binaryninja.types import (QualifiedName, Type, TypeBuilder, FunctionParameter, BoolWithConfidence, EnumerationBuilder, NamedTypeReferenceBuilder,
+from binaryninja.types import (QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, BoolWithConfidence, EnumerationBuilder, NamedTypeReferenceBuilder,
IntegerBuilder, CharBuilder, FloatBuilder, WideCharBuilder, PointerBuilder, ArrayBuilder, FunctionBuilder, StructureBuilder,
StructureMember)
@@ -450,7 +450,6 @@ class TypeBuilderTest(unittest.TestCase):
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
@@ -579,6 +578,60 @@ class TypeBuilderTest(unittest.TestCase):
assert mem.type == Type.int(4)
assert b == b.immutable_copy().mutable_copy(), "StructureBuilder failed to round trip mutability"
+ 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))
+
def test_NamedTypeReferenceBuilder(self):
b = TypeBuilder.named_type_from_type("foobar", NamedTypeReferenceClass.UnknownNamedTypeClass)
assert b.name == "foobar"
diff --git a/suite/testcommon.py b/suite/testcommon.py
index 631c626e..aa7e0945 100644
--- a/suite/testcommon.py
+++ b/suite/testcommon.py
@@ -850,6 +850,8 @@ class TestBuilder(Builder):
pass
members = s.members
+ const = s.const
+ volatile = s.volatile
s = bv.types['Foo']
assert members == s.members
assert const == s.const