https://github.com/python/cpython/commit/47c8df6172db4fc4b10d0a500d9a4bfffa5d751f
commit: 47c8df6172db4fc4b10d0a500d9a4bfffa5d751f
branch: 3.13
author: Peter Bierma <[email protected]>
committer: picnixz <[email protected]>
date: 2025-04-19T14:29:05Z
summary:
[3.13] gh-132673: Fix a crash with zero-alignment in `ctypes.Structure`
(#132695)
files:
A Misc/NEWS.d/next/Library/2025-04-18-12-45-18.gh-issue-132673.P7Z3F1.rst
M Lib/test/test_ctypes/test_aligned_structures.py
M Modules/_ctypes/stgdict.c
diff --git a/Lib/test/test_ctypes/test_aligned_structures.py
b/Lib/test/test_ctypes/test_aligned_structures.py
index a208fb9a00966a..8e8ac429900374 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
@@ -281,6 +281,41 @@ class Main(sbase):
self.assertEqual(main.b.y, 3)
self.assertEqual(main.c, 4)
+ 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)
+
if __name__ == '__main__':
unittest.main()
diff --git
a/Misc/NEWS.d/next/Library/2025-04-18-12-45-18.gh-issue-132673.P7Z3F1.rst
b/Misc/NEWS.d/next/Library/2025-04-18-12-45-18.gh-issue-132673.P7Z3F1.rst
new file mode 100644
index 00000000000000..db74ef6a324859
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-18-12-45-18.gh-issue-132673.P7Z3F1.rst
@@ -0,0 +1,2 @@
+Fix a crash when using ``_align_ = 0`` and ``_fields_ = []`` in a
+:class:`ctypes.Structure`.
diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c
index ad82e4891c519a..5f5e79e5a645fa 100644
--- a/Modules/_ctypes/stgdict.c
+++ b/Modules/_ctypes/stgdict.c
@@ -383,7 +383,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject
*fields, int isStruct
size = 0;
align = 0;
union_size = 0;
- total_align = forced_alignment;
+ total_align = forced_alignment == 0 ? 1 : forced_alignment;
stginfo->ffi_type_pointer.type = FFI_TYPE_STRUCT;
stginfo->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
if (stginfo->ffi_type_pointer.elements == NULL) {
@@ -570,6 +570,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject
*fields, int isStruct
}
/* Adjust the size according to the alignment requirements */
+ assert(total_align != 0);
aligned_size = ((size + total_align - 1) / total_align) * total_align;
if (isStruct) {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]