Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2329fa3

Browse files
committed
Fix issue with aligned subclasses
1 parent e2cceec commit 2329fa3

File tree

3 files changed

+99
-12
lines changed

3 files changed

+99
-12
lines changed

Lib/test/test_ctypes/test_aligned_structures.py

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ctypes import Structure, c_char, c_uint32, c_ubyte, alignment
1+
from ctypes import Structure, c_char, c_uint32, c_ubyte, alignment, sizeof, Union
22
import inspect
33
import unittest
44

@@ -22,11 +22,11 @@ class Main(Structure):
2222
('string', Aligned),
2323
]
2424

25-
d = Main.from_buffer(data)
26-
self.assertEqual(d.first, 7)
27-
self.assertEqual(d.string.value, b'hello world!')
25+
main = Main.from_buffer(data)
26+
self.assertEqual(main.first, 7)
27+
self.assertEqual(main.string.value, b'hello world!')
2828
self.assertEqual(
29-
bytes(d.string.__buffer__(inspect.BufferFlags.SIMPLE)),
29+
bytes(main.string.__buffer__(inspect.BufferFlags.SIMPLE)),
3030
b'\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21\x00\x00\x00\x00'
3131
)
3232

@@ -60,12 +60,12 @@ class MainTooBig(Structure):
6060
("x", SomeBoolsTooBig),
6161
("y", c_uint32),
6262
]
63-
d = Main.from_buffer(data)
64-
self.assertEqual(d.y, 7)
63+
main = Main.from_buffer(data)
64+
self.assertEqual(main.y, 7)
6565
self.assertEqual(alignment(SomeBools), 4)
66-
self.assertEqual(d.x.bool1, True)
67-
self.assertEqual(d.x.bool2, False)
68-
self.assertEqual(d.x.bool3, True)
66+
self.assertEqual(main.x.bool1, True)
67+
self.assertEqual(main.x.bool2, False)
68+
self.assertEqual(main.x.bool3, True)
6969

7070
with self.assertRaises(ValueError) as ctx:
7171
MainTooBig.from_buffer(data)
@@ -74,5 +74,92 @@ class MainTooBig(Structure):
7474
'Buffer size too small (4 instead of at least 8 bytes)'
7575
)
7676

77+
def test_aligned_subclasses(self):
78+
data = bytearray(
79+
b"\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00"
80+
)
81+
82+
class UnalignedSub(Structure):
83+
x: c_uint32
84+
_fields_ = [
85+
("x", c_uint32),
86+
]
87+
88+
class AlignedStruct(UnalignedSub):
89+
_align_ = 8
90+
y: c_uint32
91+
_fields_ = [
92+
("y", c_uint32),
93+
]
94+
95+
class Main(Structure):
96+
_fields_ = [
97+
("a", c_uint32),
98+
("b", AlignedStruct)
99+
]
100+
101+
main = Main.from_buffer(data)
102+
self.assertEqual(alignment(main.b), 8)
103+
self.assertEqual(alignment(main), 8)
104+
self.assertEqual(sizeof(main.b), 8)
105+
self.assertEqual(sizeof(main), 16)
106+
self.assertEqual(main.a, 1)
107+
self.assertEqual(main.b.x, 3)
108+
self.assertEqual(main.b.y, 4)
109+
110+
def test_aligned_union(self):
111+
data = bytearray(
112+
b"\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00"
113+
)
114+
115+
class AlignedUnion(Union):
116+
_align_ = 8
117+
_fields_ = [
118+
("a", c_uint32),
119+
("b", c_ubyte * 8),
120+
]
121+
122+
class Main(Structure):
123+
_fields_ = [
124+
("first", c_uint32),
125+
("union", AlignedUnion),
126+
]
127+
128+
main = Main.from_buffer(data)
129+
self.assertEqual(main.first, 1)
130+
self.assertEqual(main.union.a, 3)
131+
self.assertEqual(bytes(main.union.b), b"\x03\x00\x00\x00\x04\x00\x00\x00")
132+
133+
def test_aligned_struct_in_union(self):
134+
data = bytearray(
135+
b"\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00"
136+
)
137+
138+
class Sub(Structure):
139+
_align_ = 8
140+
_fields_ = [
141+
("x", c_uint32),
142+
("y", c_uint32),
143+
]
144+
145+
class MainUnion(Union):
146+
_fields_ = [
147+
("a", c_uint32),
148+
("b", Sub),
149+
]
150+
151+
class Main(Structure):
152+
_fields_ = [
153+
("first", c_uint32),
154+
("union", MainUnion),
155+
]
156+
157+
main = Main.from_buffer(data)
158+
self.assertEqual(main.first, 1)
159+
self.assertEqual(main.union.a, 3)
160+
self.assertEqual(main.union.b.x, 3)
161+
self.assertEqual(main.union.b.y, 4)
162+
163+
77164
if __name__ == '__main__':
78165
unittest.main()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Add ability to force alignment of :mod:`ctypes.Structure` by way of the new `_align_` attribute on the class.
1+
Add ability to force alignment of :mod:`ctypes.Structure` by way of the new ``_align_`` attribute on the class.

Modules/_ctypes/stgdict.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
486486
size = offset = basedict->size;
487487
align = basedict->align;
488488
union_size = 0;
489-
total_align = align ? align : forced_alignment;
489+
total_align = max(align ? align : 1, forced_alignment);
490490
stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
491491
stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
492492
if (stgdict->ffi_type_pointer.elements == NULL) {

0 commit comments

Comments
 (0)