gh-132470: Prevent crash in ctypes.CField when byte_size is incorrect (#132475)

Fix: Prevent crash in ctypes.CField when byte_size does not match type size  (gh-132470)

When creating a ctypes.CField with an incorrect byte_size (e.g., using `byte_size=2` for `ctypes.c_byte`), the code would previously abort due to the failed assertion `byte_size == info->size`.

This commit replaces the assertion with a proper error handling mechanism that raises a `ValueError` when `byte_size` does not match the expected type size. This prevents the crash and provides a more informative error message to the us

Co-authored-by: sobolevn <mail@sobolevn.me>
This commit is contained in:
dura0ok 2025-04-22 20:13:00 +07:00 committed by GitHub
parent f663b2c56a
commit 3b4b56f46d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 2 deletions

View file

@ -1,6 +1,6 @@
import unittest
import sys
from ctypes import Structure, Union, sizeof, c_char, c_int, CField
from ctypes import Structure, Union, sizeof, c_byte, c_char, c_int, CField
from ._support import Py_TPFLAGS_IMMUTABLETYPE, StructCheckMixin
@ -75,6 +75,17 @@ class FieldsTestBase(StructCheckMixin):
'ctypes state is not initialized'):
class Subclass(BrokenStructure): ...
def test_invalid_byte_size_raises_gh132470(self):
with self.assertRaisesRegex(ValueError, r"does not match type size"):
CField(
name="a",
type=c_byte,
byte_size=2, # Wrong size: c_byte is only 1 byte
byte_offset=2,
index=1,
_internal_use=True
)
def test_max_field_size_gh126937(self):
# Classes for big structs should be created successfully.
# (But they most likely can't be instantiated.)

View file

@ -0,0 +1,2 @@
Creating a :class:`ctypes.CField` with a *byte_size* that does not match the actual
type size now raises a :exc:`ValueError` instead of crashing the interpreter.

View file

@ -99,7 +99,12 @@ PyCField_new_impl(PyTypeObject *type, PyObject *name, PyObject *proto,
"type of field %R must be a C type", name);
goto error;
}
assert(byte_size == info->size);
if (byte_size != info->size) {
PyErr_Format(PyExc_ValueError,
"byte size of field %R (%zd) does not match type size (%zd)",
name, byte_size, info->size);
goto error;
}
Py_ssize_t bitfield_size = 0;
Py_ssize_t bit_offset = 0;