]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-132673: Fix `ctypes.Structure` with `_align_=0` (#132676)
authorsobolevn <mail@sobolevn.me>
Fri, 18 Apr 2025 14:32:28 +0000 (17:32 +0300)
committerGitHub <noreply@github.com>
Fri, 18 Apr 2025 14:32:28 +0000 (17:32 +0300)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Lib/ctypes/_layout.py
Lib/test/test_ctypes/test_aligned_structures.py
Misc/NEWS.d/next/Library/2025-04-18-14-34-43.gh-issue-132673.0sliCv.rst [new file with mode: 0644]

index beb3b86414c010e5ba93dcac96b2ec027ea90963..0719e72cfed312cd53da92227ed17f92a3e5b2b0 100644 (file)
@@ -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)
index 26d24f31b29f7bbdf31fb7d6f191a2817a199a1b..0c563ab80559a6f7fc481aad8d37433d76758523 100644 (file)
@@ -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 TestAlignedStructures(unittest.TestCase, StructCheckMixin):
             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 (file)
index 0000000..4d5a26c
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :exc:`AssertionError` raised on :class:`ctypes.Structure` with
+``_align_ = 0`` and ``_fields_ = []``.