Skip to content

Commit 7dc804d

Browse files
committed
fix: don't use .size of struct_impl itself, retrieve size from backing type
Structs may define their own .size attribute, breaking everything in the process
1 parent 80a4b82 commit 7dc804d

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

libdestruct/common/struct/struct_impl.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,12 @@
1515
from libdestruct.common.obj import obj
1616
from libdestruct.common.struct import struct
1717
from libdestruct.common.type_registry import TypeRegistry
18-
from libdestruct.common.utils import iterate_annotation_chain
18+
from libdestruct.common.utils import iterate_annotation_chain, size_of
1919

2020

2121
class struct_impl(struct):
2222
"""The implementation for the C struct type."""
2323

24-
size: int
25-
"""The size of the struct in bytes."""
26-
2724
_members: dict[str, obj]
2825
"""The members of the struct."""
2926

@@ -106,7 +103,7 @@ def _inflate_struct_attributes(
106103
result = resolved_type(resolver.relative_from_own(current_offset, 0))
107104
setattr(self, name, result)
108105
self._members[name] = result
109-
current_offset += result.size
106+
current_offset += size_of(result)
110107

111108
@classmethod
112109
def compute_own_size(cls: type[struct_impl], reference_type: type) -> None:
@@ -147,13 +144,13 @@ def compute_own_size(cls: type[struct_impl], reference_type: type) -> None:
147144
else:
148145
attribute = cls._inflater.inflater_for(annotation)
149146

150-
size += attribute.size
147+
size += size_of(attribute)
151148

152149
cls.size = size
153150

154151
def get(self: struct_impl) -> str:
155152
"""Return the value of the struct."""
156-
return f"{self.name}(address={self.address}, size={self.size})"
153+
return f"{self.name}(address={self.address}, size={size_of(self)})"
157154

158155
def to_bytes(self: struct_impl) -> bytes:
159156
"""Return the serialized representation of the struct."""
@@ -185,7 +182,7 @@ def __repr__(self: struct_impl) -> str:
185182
members = ",\n".join([f"{name}: {member}" for name, member in self._members.items()])
186183
return f"""{self.name} {{
187184
address: 0x{self.address:x},
188-
size: 0x{self.size:x},
185+
size: 0x{size_of(self):x},
189186
members: {{
190187
{members}
191188
}}
@@ -196,7 +193,7 @@ def __eq__(self: struct_impl, value: object) -> bool:
196193
if not isinstance(value, struct_impl):
197194
return False
198195

199-
if self.size != value.size:
196+
if size_of(self) != size_of(value):
200197
return False
201198

202199
if not self._members.keys() == value._members.keys():

libdestruct/common/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ def is_field_bound_method(item: obj) -> bool:
2525

2626
def size_of(item_or_inflater: obj | callable[[Resolver], obj]) -> int:
2727
"""Return the size of an object, from an obj or it's inflater."""
28+
if hasattr(item_or_inflater.__class__, "size"):
29+
# This has the priority over the size of the object itself
30+
# as we might be dealing with a struct object
31+
# that defines an attribute named "size"
32+
return item_or_inflater.__class__.size
2833
if hasattr(item_or_inflater, "size"):
2934
return item_or_inflater.size
3035

0 commit comments

Comments
 (0)