https://github.com/python/cpython/commit/678b8e165646e72a2f39f017ad237210d3d481ef commit: 678b8e165646e72a2f39f017ad237210d3d481ef branch: main author: sobolevn <m...@sobolevn.me> committer: sobolevn <m...@sobolevn.me> date: 2025-04-18T17:32:28+03:00 summary:
gh-132673: Fix `ctypes.Structure` with `_align_=0` (#132676) Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2025-04-18-14-34-43.gh-issue-132673.0sliCv.rst M Lib/ctypes/_layout.py M Lib/test/test_ctypes/test_aligned_structures.py diff --git a/Lib/ctypes/_layout.py b/Lib/ctypes/_layout.py index beb3b86414c010..0719e72cfed312 100644 --- a/Lib/ctypes/_layout.py +++ b/Lib/ctypes/_layout.py @@ -84,7 +84,7 @@ def get_layout(cls, input_fields, is_struct, base): raise ValueError('_align_ must be a non-negative integer') elif align == 0: # Setting `_align_ = 0` amounts to using the default alignment - align == 1 + align = 1 if base: align = max(ctypes.alignment(base), align) diff --git a/Lib/test/test_ctypes/test_aligned_structures.py b/Lib/test/test_ctypes/test_aligned_structures.py index 26d24f31b29f7b..0c563ab80559a6 100644 --- a/Lib/test/test_ctypes/test_aligned_structures.py +++ b/Lib/test/test_ctypes/test_aligned_structures.py @@ -1,7 +1,7 @@ from ctypes import ( c_char, c_uint32, c_uint16, c_ubyte, c_byte, alignment, sizeof, BigEndianStructure, LittleEndianStructure, - BigEndianUnion, LittleEndianUnion, + BigEndianUnion, LittleEndianUnion, Structure, ) import struct import unittest @@ -69,6 +69,41 @@ class Main(base): self.assertEqual(Main.z.offset, 8) self.assertEqual(main.z, 7) + def test_negative_align(self): + for base in (Structure, LittleEndianStructure, BigEndianStructure): + with ( + self.subTest(base=base), + self.assertRaisesRegex( + ValueError, + '_align_ must be a non-negative integer', + ) + ): + class MyStructure(base): + _align_ = -1 + _fields_ = [] + + def test_zero_align_no_fields(self): + for base in (Structure, LittleEndianStructure, BigEndianStructure): + with self.subTest(base=base): + class MyStructure(base): + _align_ = 0 + _fields_ = [] + + self.assertEqual(alignment(MyStructure), 1) + self.assertEqual(alignment(MyStructure()), 1) + + def test_zero_align_with_fields(self): + for base in (Structure, LittleEndianStructure, BigEndianStructure): + with self.subTest(base=base): + class MyStructure(base): + _align_ = 0 + _fields_ = [ + ("x", c_ubyte), + ] + + self.assertEqual(alignment(MyStructure), 1) + self.assertEqual(alignment(MyStructure()), 1) + def test_oversized_structure(self): data = bytearray(b"\0" * 8) for base in (LittleEndianStructure, BigEndianStructure): diff --git a/Misc/NEWS.d/next/Library/2025-04-18-14-34-43.gh-issue-132673.0sliCv.rst b/Misc/NEWS.d/next/Library/2025-04-18-14-34-43.gh-issue-132673.0sliCv.rst new file mode 100644 index 00000000000000..4d5a26caf0ea90 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-18-14-34-43.gh-issue-132673.0sliCv.rst @@ -0,0 +1,2 @@ +Fix :exc:`AssertionError` raised on :class:`ctypes.Structure` with +``_align_ = 0`` and ``_fields_ = []``. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com