8000 [3.13] gh-132673: Fix a crash with zero-alignment in `ctypes.Structur… · python/cpython@47c8df6 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 47c8df6

Browse files
[3.13] gh-132673: Fix a crash with zero-alignment in ctypes.Structure (#132695)
1 parent 38f305b commit 47c8df6

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

Lib/test/test_ctypes/test_aligned_structures.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from ctypes import (
22
c_char, c_uint32, c_uint16, c_ubyte, c_byte, alignment, sizeof,
33
BigEndianStructure, LittleEndianStructure,
4-
BigEndianUnion, LittleEndianUnion,
4+
BigEndianUnion, LittleEndianUnion, Structure
55
)
66
import struct
77
import unittest
@@ -281,6 +281,41 @@ class Main(sbase):
281281
self.assertEqual(main.b.y, 3)
282282
self.assertEqual(main.c, 4)
283283

284+
def test_negative_align(self):
285+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
286+
with (
287+
self.subTest(base=base),
288+
self.assertRaisesRegex(
289+
ValueError,
290+
'_align_ must be a non-negative integer',
291+
)
292+
):
293+
class MyStructure(base):
294+
_align_ = -1
295+
_fields_ = []
296+
297+
def test_zero_align_no_fields(self):
298+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
299+
with self.subTest(base=base):
300+
class MyStructure(base):
301+
_align_ = 0
302+
_fields_ = []
303+
304+
self.assertEqual(alignment(MyStructure), 1)
305+
self.assertEqual(alignment(MyStructure()), 1)
306+
307+
def test_zero_align_with_fields(self):
308+
for base in (Structure, LittleEndianStructure, BigEndianStructure):
309+
with self.subTest(base=base):
310+
class MyStructure(base):
311+
_align_ = 0
312+
_fields_ = [
313+
("x", c_ubyte),
314+
]
315+
316+
self.assertEqual(alignment(MyStructure), 1)
317+
self.assertEqual(alignment(MyStructure()), 1)
318+
284319

285320
if __name__ == '__main__':
286321
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash when using ``_align_ = 0`` and ``_fields_ = []`` in a
2+
:class:`ctypes.Structure`.

Modules/_ctypes/stgdict.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
383383
size = 0;
384384
align = 0;
385385
union_size = 0;
386-
total_align = forced_alignment;
386+
total_align = forced_alignment == 0 ? 1 : forced_alignment;
387387
stginfo->ffi_type_pointer.type = FFI_TYPE_STRUCT;
388388
stginfo->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
389389
if (stginfo->ffi_type_pointer.elements == NULL) {
@@ -570,6 +570,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
570570
}
571571

572572
/* Adjust the size according to the alignment requirements */
573+
assert(total_align != 0);
573574
aligned_size = ((size + total_align - 1) / total_align) * total_align;
574575

575576
if (isStruct) {

0 commit comments

Comments
 (0)
0