diff --git a/dissect/cstruct/types/structure.py b/dissect/cstruct/types/structure.py index 6c67516..ef8927b 100644 --- a/dissect/cstruct/types/structure.py +++ b/dissect/cstruct/types/structure.py @@ -324,6 +324,12 @@ def _calc_size_and_offsets(self) -> None: size = max(len(field.type), size) alignment = max(field.alignment, alignment) + if self.align and size is not None: + # Add "tail padding" if we need to align + # This bit magic rounds up to the next alignment boundary + # E.g. offset = 3; alignment = 8; -offset & (alignment - 1) = 5 + size += -size & (alignment - 1) + self.size = size self.alignment = alignment diff --git a/tests/test_align.py b/tests/test_align.py index 7e92a2b..859a879 100644 --- a/tests/test_align.py +++ b/tests/test_align.py @@ -72,6 +72,21 @@ def test_align_union(): assert obj.dumps() == buf +def test_align_union_tail(): + d = """ + union test { + uint64 a; + uint32 b[3]; + }; + """ + c = cstruct.cstruct() + c.load(d, align=True) + + assert c.test.align + assert c.test.alignment == 8 + assert c.test.size == 16 + + def test_align_array(): d = """ struct test {