[3.13] gh-132673: Fix a crash with zero-alignment in ctypes.Structure (#132695)

This commit is contained in:
Peter Bierma 2025-04-19 10:29:05 -04:00 committed by GitHub
parent 38f305b9db
commit 47c8df6172
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 2 deletions

View 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
@ -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()

View file

@ -0,0 +1,2 @@
Fix a crash when using ``_align_ = 0`` and ``_fields_ = []`` in a
:class:`ctypes.Structure`.

View file

@ -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) {